rspack_plugin_mf/container/
module_federation_runtime_plugin.rs

1//! # ModuleFederationRuntimePlugin
2//!
3//! Main orchestration plugin for Module Federation runtime functionality.
4//! Coordinates federation plugins, manages runtime dependencies, and adds the base FederationRuntimeModule.
5
6use rspack_core::{
7  BoxDependency, ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements,
8  CompilerFinishMake, EntryOptions, Plugin, RuntimeGlobals,
9};
10use rspack_error::Result;
11use rspack_hook::{plugin, plugin_hook};
12use serde::Deserialize;
13
14use super::{
15  embed_federation_runtime_plugin::EmbedFederationRuntimePlugin,
16  federation_data_runtime_module::FederationDataRuntimeModule,
17  federation_modules_plugin::FederationModulesPlugin,
18  federation_runtime_dependency::FederationRuntimeDependency,
19  hoist_container_references_plugin::HoistContainerReferencesPlugin,
20};
21
22#[derive(Debug, Default, Deserialize, Clone)]
23pub struct ModuleFederationRuntimePluginOptions {
24  pub entry_runtime: Option<String>,
25}
26
27#[plugin]
28#[derive(Debug)]
29pub struct ModuleFederationRuntimePlugin {
30  options: ModuleFederationRuntimePluginOptions,
31}
32
33impl ModuleFederationRuntimePlugin {
34  pub fn new(options: ModuleFederationRuntimePluginOptions) -> Self {
35    Self::new_inner(options)
36  }
37}
38
39#[plugin_hook(CompilationAdditionalTreeRuntimeRequirements for ModuleFederationRuntimePlugin)]
40async fn additional_tree_runtime_requirements(
41  &self,
42  compilation: &mut Compilation,
43  chunk_ukey: &ChunkUkey,
44  _runtime_requirements: &mut RuntimeGlobals,
45) -> Result<()> {
46  // Add base FederationRuntimeModule which is responsible for providing bundler data to the runtime.
47  compilation.add_runtime_module(chunk_ukey, Box::<FederationDataRuntimeModule>::default())?;
48
49  Ok(())
50}
51
52#[plugin_hook(CompilerFinishMake for ModuleFederationRuntimePlugin)]
53async fn finish_make(&self, compilation: &mut Compilation) -> Result<()> {
54  if let Some(entry_request) = self.options.entry_runtime.clone() {
55    let federation_runtime_dep = FederationRuntimeDependency::new(entry_request.clone());
56
57    let hooks = FederationModulesPlugin::get_compilation_hooks(compilation);
58
59    hooks
60      .add_federation_runtime_dependency
61      .lock()
62      .await
63      .call(&federation_runtime_dep)
64      .await?;
65
66    let boxed_dep: BoxDependency = Box::new(federation_runtime_dep);
67    let entry_options = EntryOptions::default();
68    let args = vec![(boxed_dep, entry_options)];
69
70    compilation.add_include(args).await?;
71  }
72
73  Ok(())
74}
75
76impl Plugin for ModuleFederationRuntimePlugin {
77  fn name(&self) -> &'static str {
78    "rspack.container.ModuleFederationRuntimePlugin"
79  }
80
81  fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> {
82    ctx
83      .compilation_hooks
84      .additional_tree_runtime_requirements
85      .tap(additional_tree_runtime_requirements::new(self));
86
87    ctx.compiler_hooks.finish_make.tap(finish_make::new(self));
88
89    // Apply supporting plugins
90    EmbedFederationRuntimePlugin::default().apply(ctx)?;
91    HoistContainerReferencesPlugin::default().apply(ctx)?;
92
93    Ok(())
94  }
95}