@@ -7,11 +7,12 @@ use derive_more::Debug;
77use futures:: future:: BoxFuture ;
88use rspack_collections:: { Identifiable , IdentifierMap } ;
99use rspack_core:: {
10- BoxDependency , ChunkByUkey , ChunkNamedIdArtifact , ChunkUkey , Compilation , CompilationChunkIds ,
11- CompilationParams , CompilationRuntimeRequirementInTree , CompilerCompilation , CompilerDone ,
12- CompilerFailed , CompilerFinishMake , CompilerThisCompilation , Dependency , DependencyId ,
13- DependencyType , EntryDependency , EntryOptions , Logger , Plugin , RuntimeGlobals , RuntimeModule ,
14- RuntimeSpec , get_entry_runtime,
10+ BoxDependency , ChunkByUkey , ChunkNamedIdArtifact , ChunkUkey , Compilation ,
11+ CompilationAdditionalModuleRuntimeRequirements , CompilationChunkIds , CompilationParams ,
12+ CompilationRuntimeRequirementInTree , CompilerCompilation , CompilerDone , CompilerFailed ,
13+ CompilerFinishMake , CompilerThisCompilation , Dependency , DependencyId , DependencyType ,
14+ EntryDependency , EntryOptions , Logger , Module , ModuleIdentifier , Plugin , RuntimeGlobals ,
15+ RuntimeModule , RuntimeSpec , get_entry_runtime,
1516} ;
1617use rspack_error:: { Diagnostic , Result , ToStringResultToRspackResultExt } ;
1718use rspack_hook:: { plugin, plugin_hook} ;
@@ -23,6 +24,7 @@ use crate::{
2324 } ,
2425 constants:: { CSS_REGEX , LAYERS_NAMES } ,
2526 coordinator:: Coordinator ,
27+ ensure_server_actions_runtime_module:: RscEnsureServerActionsRuntimeModule ,
2628 hot_reloader:: track_server_component_changes,
2729 loaders:: action_entry_loader:: ACTION_ENTRY_LOADER_IDENTIFIER ,
2830 manifest_runtime_module:: RscManifestRuntimeModule ,
@@ -184,9 +186,77 @@ async fn runtime_requirements_in_tree(
184186 Box :: new ( RscManifestRuntimeModule :: new ( & compilation. runtime_template ) ) ,
185187 ) ) ;
186188 }
189+ if runtime_requirements. contains ( RuntimeGlobals :: RSC_ENSURE_SERVER_ACTIONS ) {
190+ runtime_modules_to_add. push ( (
191+ * chunk_ukey,
192+ Box :: new ( RscEnsureServerActionsRuntimeModule :: new (
193+ & compilation. runtime_template ,
194+ ) ) ,
195+ ) ) ;
196+ }
187197 Ok ( None )
188198}
189199
200+ #[ plugin_hook( CompilationAdditionalModuleRuntimeRequirements for RscServerPlugin , tracing=false ) ]
201+ async fn additional_module_runtime_requirements (
202+ & self ,
203+ compilation : & Compilation ,
204+ module_identifier : & ModuleIdentifier ,
205+ runtime_requirements : & mut RuntimeGlobals ,
206+ ) -> Result < ( ) > {
207+ let Some ( module) = compilation. module_by_identifier ( module_identifier) else {
208+ return Ok ( ( ) ) ;
209+ } ;
210+
211+ if module_needs_ensure_server_actions_runtime ( module. as_ref ( ) , compilation) {
212+ runtime_requirements
213+ . insert ( RuntimeGlobals :: REQUIRE | RuntimeGlobals :: RSC_ENSURE_SERVER_ACTIONS ) ;
214+ }
215+
216+ Ok ( ( ) )
217+ }
218+
219+ fn has_server_actions ( module : & dyn Module ) -> bool {
220+ module
221+ . build_info ( )
222+ . rsc
223+ . as_ref ( )
224+ . is_some_and ( |rsc| !rsc. action_ids . is_empty ( ) )
225+ }
226+
227+ fn is_rsc_layer_module ( module : & dyn Module ) -> bool {
228+ module
229+ . get_layer ( )
230+ . is_some_and ( |layer| layer == LAYERS_NAMES . react_server_components )
231+ }
232+
233+ fn module_needs_ensure_server_actions_runtime (
234+ module : & dyn Module ,
235+ compilation : & Compilation ,
236+ ) -> bool {
237+ if !is_rsc_layer_module ( module) {
238+ return false ;
239+ }
240+
241+ if has_server_actions ( module) {
242+ return true ;
243+ }
244+
245+ let Some ( concatenated_module) = module. as_concatenated_module ( ) else {
246+ return false ;
247+ } ;
248+
249+ let module_graph = compilation. get_module_graph ( ) ;
250+ concatenated_module
251+ . get_modules ( )
252+ . iter ( )
253+ . any ( |inner_module| {
254+ module_graph
255+ . module_by_identifier ( & inner_module. id )
256+ . is_some_and ( |module| has_server_actions ( module. as_ref ( ) ) )
257+ } )
258+ }
259+
190260/// Compute server manifest and server_consumer_module_map once per entry. Stored in plugin_state for
191261/// RscManifestRuntimeModule and onManifest to avoid recomputing.
192262#[ plugin_hook( CompilationChunkIds for RscServerPlugin , stage = -10000 ) ]
@@ -227,6 +297,10 @@ impl Plugin for RscServerPlugin {
227297 . compilation_hooks
228298 . runtime_requirement_in_tree
229299 . tap ( runtime_requirements_in_tree:: new ( self ) ) ;
300+ ctx
301+ . compilation_hooks
302+ . additional_module_runtime_requirements
303+ . tap ( additional_module_runtime_requirements:: new ( self ) ) ;
230304
231305 ctx. compilation_hooks . chunk_ids . tap ( chunk_ids:: new ( self ) ) ;
232306
0 commit comments