@@ -4,18 +4,25 @@ use next_core::{
44 next_manifests:: { ActionLayer , ActionManifestWorkerEntry , ServerReferenceManifest } ,
55 util:: NextRuntime ,
66} ;
7- use turbo_rcstr:: RcStr ;
7+ use turbo_rcstr:: { RcStr , rcstr } ;
88use turbo_tasks:: { NonLocalValue , ResolvedVc , TryJoinIterExt , Vc , trace:: TraceRawVcs } ;
9- use turbo_tasks_fs:: { self , File , FileContent , FileSystemPath } ;
9+ use turbo_tasks_fs:: { self , File , FileContent , FileSystem , FileSystemPath , VirtualFileSystem } ;
1010use turbopack_core:: {
11+ self ,
1112 asset:: AssetContent ,
12- chunk:: ChunkingContext ,
13- emit_collect:: EmittedModuleReference ,
14- module:: Module ,
13+ chunk:: { AsyncModuleInfo , ChunkItem , ChunkableModule , ChunkingContext , EvaluatableAsset } ,
14+ emit_collect:: { CollectingModule , EmittedModuleReference } ,
15+ ident:: AssetIdent ,
16+ module:: { Module , ModuleSideEffects , Modules } ,
1517 module_graph:: { ModuleGraph , async_module_info:: AsyncModulesInfo } ,
1618 output:: OutputAsset ,
19+ reference:: ModuleReferences ,
20+ source:: OptionSource ,
1721 virtual_output:: VirtualOutputAsset ,
1822} ;
23+ use turbopack_ecmascript:: chunk:: {
24+ EcmascriptChunkItemContent , EcmascriptChunkPlaceable , EcmascriptExports , ecmascript_chunk_item,
25+ } ;
1926
2027/// Scans the RSC entry point's full module graph looking for emitted Server
2128/// Actions, and a manifest describing the found actions.
@@ -47,19 +54,15 @@ async fn collect_actions(
4754 server_action_loader : ResolvedVc < Box < dyn Module > > ,
4855 module_graph : Vc < ModuleGraph > ,
4956) -> Result < Vc < AllActions > > {
57+ // This mirrors what the ServerActionCollectModule ends up chunking into the chunk.
5058 let collected_modules = module_graph. collected_modules ( ) . await ?;
51-
52- // This mirrors what the __turbopack_collect__ in
53- // packages/next/src/build/templates/turbopack-action-loader.ts ends up chunking into the chunk.
54-
5559 // This can be none if there are no server actions
5660 let actions =
5761 collected_modules
5862 . collected_references
5963 . iter ( )
60- . find_map ( |( ( entry, _loader) , actions) | {
61- if * entry == server_action_loader {
62- // TODO also filter based on _loader
64+ . find_map ( |( ( entry, loader) , actions) | {
65+ if * entry == server_action_loader && * loader == server_action_loader {
6366 Some ( actions)
6467 } else {
6568 None
@@ -201,3 +204,113 @@ type HashToLayerNameModule = Vec<(
201204/// and exported name of each found action.
202205#[ turbo_tasks:: value( transparent) ]
203206pub struct AllActions ( HashToLayerNameModule ) ;
207+
208+ /// This module performs what `__turbopack_collect__({namespace: 'next/server-actions'})` would do
209+ /// chunking-wise. Except that we collect the list manually into a separate JSON, so
210+ /// __turbopack_collect__ would unnecessarily codegen a big list of server actions.
211+ #[ turbo_tasks:: value]
212+ pub struct ServerActionCollectModule {
213+ namespace : RcStr ,
214+ page : RcStr ,
215+ }
216+
217+ #[ turbo_tasks:: value_impl]
218+ impl ServerActionCollectModule {
219+ #[ turbo_tasks:: function]
220+ pub fn new ( namespace : RcStr , page : RcStr ) -> Vc < Self > {
221+ ServerActionCollectModule { namespace, page } . cell ( )
222+ }
223+ }
224+
225+ #[ turbo_tasks:: function]
226+ fn server_actions_collect_virtual_fs ( ) -> Vc < VirtualFileSystem > {
227+ VirtualFileSystem :: new_with_name ( rcstr ! ( "next-server-actions-collect" ) )
228+ }
229+
230+ #[ turbo_tasks:: value_impl]
231+ impl Module for ServerActionCollectModule {
232+ #[ turbo_tasks:: function]
233+ async fn ident ( & self ) -> Result < Vc < AssetIdent > > {
234+ Ok (
235+ AssetIdent :: from_path ( server_actions_collect_virtual_fs ( ) . root ( ) . owned ( ) . await ?)
236+ . with_modifier ( self . namespace . clone ( ) )
237+ . with_modifier ( self . page . clone ( ) ) ,
238+ )
239+ }
240+
241+ #[ turbo_tasks:: function]
242+ fn source ( & self ) -> Vc < OptionSource > {
243+ Vc :: cell ( None )
244+ }
245+
246+ #[ turbo_tasks:: function]
247+ fn references ( & self ) -> Vc < ModuleReferences > {
248+ ModuleReferences :: empty ( )
249+ }
250+
251+ #[ turbo_tasks:: function]
252+ fn side_effects ( self : Vc < Self > ) -> Vc < ModuleSideEffects > {
253+ ModuleSideEffects :: SideEffectful . cell ( )
254+ }
255+ }
256+
257+ #[ turbo_tasks:: value_impl]
258+ impl CollectingModule for ServerActionCollectModule {
259+ #[ turbo_tasks:: function]
260+ fn namespace ( & self ) -> Vc < RcStr > {
261+ Vc :: cell ( self . namespace . clone ( ) )
262+ }
263+
264+ #[ turbo_tasks:: function]
265+ fn as_chunk_item (
266+ self : ResolvedVc < Self > ,
267+ module_graph : ResolvedVc < ModuleGraph > ,
268+ chunking_context : ResolvedVc < Box < dyn ChunkingContext > > ,
269+ _chunk_group : Vc < Modules > ,
270+ ) -> Vc < Box < dyn ChunkItem > > {
271+ ecmascript_chunk_item ( ResolvedVc :: upcast ( self ) , module_graph, chunking_context)
272+ }
273+ }
274+
275+ #[ turbo_tasks:: value_impl]
276+ impl ChunkableModule for ServerActionCollectModule {
277+ #[ turbo_tasks:: function]
278+ fn as_chunk_item (
279+ self : ResolvedVc < Self > ,
280+ module_graph : ResolvedVc < ModuleGraph > ,
281+ chunking_context : ResolvedVc < Box < dyn ChunkingContext > > ,
282+ ) -> Vc < Box < dyn ChunkItem > > {
283+ ecmascript_chunk_item ( ResolvedVc :: upcast ( self ) , module_graph, chunking_context)
284+ }
285+ }
286+
287+ #[ turbo_tasks:: value_impl]
288+ impl EcmascriptChunkPlaceable for ServerActionCollectModule {
289+ #[ turbo_tasks:: function]
290+ fn get_exports ( & self ) -> Vc < EcmascriptExports > {
291+ EcmascriptExports :: None . cell ( )
292+ }
293+
294+ #[ turbo_tasks:: function]
295+ async fn chunk_item_content (
296+ self : Vc < Self > ,
297+ _chunking_context : Vc < Box < dyn ChunkingContext > > ,
298+ _module_graph : Vc < ModuleGraph > ,
299+ _async_module_info : Option < Vc < AsyncModuleInfo > > ,
300+ _estimated : bool ,
301+ ) -> Result < Vc < EcmascriptChunkItemContent > > {
302+ // There is no runtime behavior needed here.
303+ // - __turbopack_collect__ causes all modules to chunked together with this one
304+ // - server-reference-manifest.json will contains all the module ids from above. It will do
305+ // the loading itself
306+ // In the future, when server-reference-manifest might be loaded/handled by the templates
307+ // themselves, then it could happen here instead.
308+ Ok ( EcmascriptChunkItemContent {
309+ ..Default :: default ( )
310+ }
311+ . cell ( ) )
312+ }
313+ }
314+
315+ #[ turbo_tasks:: value_impl]
316+ impl EvaluatableAsset for ServerActionCollectModule { }
0 commit comments