Skip to content

Commit 854fea2

Browse files
committed
ServerActionCollectModule
1 parent 934cecc commit 854fea2

File tree

4 files changed

+135
-51
lines changed

4 files changed

+135
-51
lines changed

crates/next-api/src/app.rs

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ use next_core::{
3333
next_server_utility::{NEXT_SERVER_UTILITY_MERGE_TAG, NextServerUtilityTransition},
3434
parse_segment_config_from_source,
3535
segment_config::{NextSegmentConfig, ParseSegmentMode},
36-
util::{
37-
NextRuntime, app_function_name, module_styles_rule_condition, styles_rule_condition,
38-
virtual_next_js_template_path,
39-
},
36+
util::{NextRuntime, app_function_name, module_styles_rule_condition, styles_rule_condition},
4037
};
4138
use tracing::Instrument;
4239
use turbo_rcstr::{RcStr, rcstr};
@@ -56,7 +53,6 @@ use turbopack_core::{
5653
ChunkGroupResult, ChunkingContext, ChunkingContextExt, EvaluatableAssets, SourceMapsType,
5754
availability_info::AvailabilityInfo,
5855
},
59-
context::AssetContext,
6056
file_source::FileSource,
6157
ident::{AssetIdent, Layer},
6258
module::Module,
@@ -67,9 +63,7 @@ use turbopack_core::{
6763
},
6864
output::{OutputAsset, OutputAssets, OutputAssetsWithReferenced},
6965
reference::all_assets_from_entries,
70-
reference_type::{
71-
CommonJsReferenceSubType, CssReferenceSubType, ReferenceType, ReferenceTypeCondition,
72-
},
66+
reference_type::{CommonJsReferenceSubType, CssReferenceSubType, ReferenceTypeCondition},
7367
resolve::{ResolveErrorMode, origin::PlainResolveOrigin, parse::Request, pattern::Pattern},
7468
source::Source,
7569
source_map::SourceMapAsset,
@@ -92,7 +86,7 @@ use crate::{
9286
route::{
9387
AppPageRoute, Endpoint, EndpointOutput, EndpointOutputPaths, ModuleGraphs, Route, Routes,
9488
},
95-
server_actions::create_server_actions_manifest,
89+
server_actions::{ServerActionCollectModule, create_server_actions_manifest},
9690
sri_manifest::get_sri_manifest_asset,
9791
webpack_stats::generate_webpack_stats,
9892
};
@@ -1287,27 +1281,13 @@ impl AppEndpoint {
12871281
#[turbo_tasks::function]
12881282
async fn server_action_loader_module(self: Vc<Self>) -> Result<Vc<Box<dyn Module>>> {
12891283
let this = self.await?;
1290-
let app_entry = self.app_endpoint_entry().await?;
1291-
let runtime = app_entry.config.await?.runtime.unwrap_or_default();
1292-
1293-
let module_context = match runtime {
1294-
NextRuntime::Edge => this.app_project.edge_rsc_module_context(),
1295-
NextRuntime::NodeJs => this.app_project.rsc_module_context(),
1296-
};
1284+
// let app_entry = self.app_endpoint_entry().await?;
1285+
// let runtime = app_entry.config.await?.runtime.unwrap_or_default();
12971286

1298-
Ok(module_context
1299-
.process(
1300-
Vc::upcast(FileSource::new_with_query(
1301-
virtual_next_js_template_path(
1302-
this.app_project.project().project_path().owned().await?,
1303-
"turbopack-action-loader.js",
1304-
)
1305-
.await?,
1306-
RcStr::from(format!("?{}", this.page)),
1307-
)),
1308-
ReferenceType::Undefined,
1309-
)
1310-
.module())
1287+
Ok(Vc::upcast(ServerActionCollectModule::new(
1288+
rcstr!("next/server-actions"),
1289+
this.page.to_string().into(),
1290+
)))
13111291
}
13121292

13131293
#[turbo_tasks::function]

crates/next-api/src/server_actions.rs

Lines changed: 125 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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};
88
use 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};
1010
use 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)]
203206
pub 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 {}

crates/next-core/src/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ pub async fn file_content_rope(content: Vc<FileContent>) -> Result<Vc<Rope>> {
459459
Ok(file.content().to_owned().cell())
460460
}
461461

462-
pub async fn virtual_next_js_template_path(
462+
async fn virtual_next_js_template_path(
463463
project_path: FileSystemPath,
464464
file: &str,
465465
) -> Result<FileSystemPath> {

packages/next/src/build/templates/turbopack-action-loader.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)