rspack_plugin_runtime 0.100.1

rspack runtime plugin
Documentation
use std::iter;

use itertools::Itertools;
use rspack_core::{
  Compilation, RuntimeGlobals, RuntimeModule, RuntimeModuleGenerateContext, RuntimeTemplate,
  impl_runtime_module,
};

#[impl_runtime_module]
#[derive(Debug)]
pub struct StartupChunkDependenciesRuntimeModule {
  async_chunk_loading: bool,
}

impl StartupChunkDependenciesRuntimeModule {
  pub fn new(runtime_template: &RuntimeTemplate, async_chunk_loading: bool) -> Self {
    Self::with_default(runtime_template, async_chunk_loading)
  }
}

#[async_trait::async_trait]
impl RuntimeModule for StartupChunkDependenciesRuntimeModule {
  fn template(&self) -> Vec<(String, String)> {
    vec![(
      self.id.to_string(),
      include_str!("runtime/startup_chunk_dependencies.ejs").to_string(),
    )]
  }

  async fn generate(
    &self,
    context: &RuntimeModuleGenerateContext<'_>,
  ) -> rspack_error::Result<String> {
    let compilation = context.compilation;
    let runtime_template = context.runtime_template;
    if let Some(chunk_ukey) = self.chunk {
      let chunk_ids = compilation
        .build_chunk_graph_artifact
        .chunk_graph
        .get_chunk_entry_dependent_chunks_iterable(
          &chunk_ukey,
          &compilation.build_chunk_graph_artifact.chunk_by_ukey,
          &compilation.build_chunk_graph_artifact.chunk_group_by_ukey,
        )
        .map(|chunk_ukey| {
          compilation
            .build_chunk_graph_artifact
            .chunk_by_ukey
            .expect_get(&chunk_ukey)
            .expect_id()
            .clone()
        })
        .collect::<Vec<_>>();

      let body = if self.async_chunk_loading {
        match chunk_ids.len() {
          1 => format!(
            "return {}({}).then(next);",
            runtime_template.render_runtime_globals(&RuntimeGlobals::ENSURE_CHUNK),
            rspack_util::json_stringify(chunk_ids.first().expect("Should has at least one chunk"))
          ),
          2 => format!(
            "return Promise.all([{}]).then(next);",
            chunk_ids
              .iter()
              .map(|cid| format!(
                "{}({})",
                runtime_template.render_runtime_globals(&RuntimeGlobals::ENSURE_CHUNK),
                rspack_util::json_stringify(cid)
              ))
              .join(",\n")
          ),
          _ => format!(
            "return Promise.all({}.map({}, {})).then(next);",
            serde_json::to_string(&chunk_ids).expect("Invalid json to string"),
            runtime_template.render_runtime_globals(&RuntimeGlobals::ENSURE_CHUNK),
            runtime_template.render_runtime_globals(&RuntimeGlobals::REQUIRE)
          ),
        }
      } else {
        chunk_ids
          .iter()
          .map(|cid| {
            format!(
              "{}({});",
              runtime_template.render_runtime_globals(&RuntimeGlobals::ENSURE_CHUNK),
              rspack_util::json_stringify(cid)
            )
          })
          .chain(iter::once("return next();".to_string()))
          .join("\n")
      };

      let source = runtime_template.render(
        &self.id,
        Some(serde_json::json!({
          "_body": body,
        })),
      )?;

      Ok(source)
    } else {
      unreachable!("should have chunk for StartupChunkDependenciesRuntimeModule")
    }
  }

  fn additional_runtime_requirements(&self, _compilation: &Compilation) -> RuntimeGlobals {
    RuntimeGlobals::STARTUP
      | RuntimeGlobals::ENSURE_CHUNK
      | RuntimeGlobals::ENSURE_CHUNK_INCLUDE_ENTRIES
  }
}