rspack_plugin_runtime_chunk/
lib.rs1use std::fmt;
2
3use futures::future::BoxFuture;
4use rspack_core::{Compilation, CompilationAddEntry};
5use rspack_error::Result;
6use rspack_hook::{plugin, plugin_hook};
7
8#[plugin]
9#[derive(Debug)]
10pub struct RuntimeChunkPlugin {
11 name: RuntimeChunkName,
12}
13
14impl RuntimeChunkPlugin {
15 pub fn new(options: RuntimeChunkOptions) -> Self {
16 Self::new_inner(options.name)
17 }
18}
19
20#[derive(Debug)]
21pub struct RuntimeChunkOptions {
22 pub name: RuntimeChunkName,
23}
24
25pub enum RuntimeChunkName {
26 Single,
27 Multiple,
28 String(String),
29 Fn(RuntimeChunkNameFn),
30}
31
32impl fmt::Debug for RuntimeChunkName {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 Self::Single => write!(f, "Single"),
36 Self::Multiple => write!(f, "Multiple"),
37 Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(),
38 Self::Fn(_) => f.debug_tuple("Fn").finish(),
39 }
40 }
41}
42
43pub type RuntimeChunkNameFn =
44 Box<dyn for<'a> Fn(&'a str) -> BoxFuture<'a, Result<String>> + Sync + Send>;
45
46#[plugin_hook(CompilationAddEntry for RuntimeChunkPlugin)]
47async fn add_entry(&self, compilation: &mut Compilation, entry_name: Option<&str>) -> Result<()> {
48 if let Some(entry_name) = entry_name
49 && let Some(data) = compilation.entries.get_mut(entry_name)
50 && data.options.runtime.is_none()
51 && data.options.depend_on.is_none()
52 {
53 let name = match &self.name {
54 RuntimeChunkName::Single => "runtime".to_string(),
55 RuntimeChunkName::Multiple => {
56 format!("runtime~{entry_name}")
57 }
58 RuntimeChunkName::String(name) => name.clone(),
59 RuntimeChunkName::Fn(f) => f(entry_name).await?,
60 };
61 data.options.runtime = Some(name.into());
62 }
63 Ok(())
64}
65
66impl rspack_core::Plugin for RuntimeChunkPlugin {
67 fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> {
68 ctx.compilation_hooks.add_entry.tap(add_entry::new(self));
69 Ok(())
70 }
71}