Skip to content

Commit 03f095b

Browse files
committed
WIP server actions
1 parent b4c478e commit 03f095b

File tree

5 files changed

+239
-234
lines changed

5 files changed

+239
-234
lines changed

crates/next-api/src/app.rs

Lines changed: 118 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ 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::{NextRuntime, app_function_name, module_styles_rule_condition, styles_rule_condition},
36+
util::{
37+
NextRuntime, app_function_name, module_styles_rule_condition, styles_rule_condition,
38+
virtual_next_js_template_path,
39+
},
3740
};
3841
use tracing::Instrument;
3942
use turbo_rcstr::{RcStr, rcstr};
@@ -50,9 +53,10 @@ use turbopack::{
5053
use turbopack_core::{
5154
asset::AssetContent,
5255
chunk::{
53-
ChunkGroupResult, ChunkingContext, ChunkingContextExt, EvaluatableAsset, EvaluatableAssets,
54-
SourceMapsType, availability_info::AvailabilityInfo,
56+
ChunkGroupResult, ChunkingContext, ChunkingContextExt, EvaluatableAssets, SourceMapsType,
57+
availability_info::AvailabilityInfo,
5558
},
59+
context::AssetContext,
5660
file_source::FileSource,
5761
ident::{AssetIdent, Layer},
5862
module::Module,
@@ -63,7 +67,9 @@ use turbopack_core::{
6367
},
6468
output::{OutputAsset, OutputAssets, OutputAssetsWithReferenced},
6569
reference::all_assets_from_entries,
66-
reference_type::{CommonJsReferenceSubType, CssReferenceSubType, ReferenceTypeCondition},
70+
reference_type::{
71+
CommonJsReferenceSubType, CssReferenceSubType, ReferenceType, ReferenceTypeCondition,
72+
},
6773
resolve::{ResolveErrorMode, origin::PlainResolveOrigin, parse::Request, pattern::Pattern},
6874
source::Source,
6975
source_map::SourceMapAsset,
@@ -76,7 +82,7 @@ use crate::{
7682
dynamic_imports::{NextDynamicChunkAvailability, collect_next_dynamic_chunks},
7783
font::FontManifest,
7884
loadable_manifest::create_react_loadable_manifest,
79-
module_graph::{ClientReferencesGraphs, NextDynamicGraphs, ServerActionsGraphs},
85+
module_graph::{ClientReferencesGraphs, NextDynamicGraphs},
8086
nft_json::NftJsonAsset,
8187
paths::{
8288
all_asset_paths, all_paths_in_root, get_asset_paths_from_root, get_js_paths_from_root,
@@ -86,7 +92,7 @@ use crate::{
8692
route::{
8793
AppPageRoute, Endpoint, EndpointOutput, EndpointOutputPaths, ModuleGraphs, Route, Routes,
8894
},
89-
server_actions::{build_server_actions_loader, create_server_actions_manifest},
95+
server_actions::create_server_actions_manifest,
9096
sri_manifest::get_sri_manifest_asset,
9197
webpack_stats::generate_webpack_stats,
9298
};
@@ -100,7 +106,6 @@ pub struct AppProject {
100106
#[turbo_tasks::value(transparent)]
101107
pub struct OptionAppProject(Option<ResolvedVc<AppProject>>);
102108

103-
impl AppProject {}
104109
impl AppProject {
105110
pub fn client_transition_name() -> RcStr {
106111
rcstr!("next-ecmascript-client-reference")
@@ -792,6 +797,11 @@ impl AppProject {
792797
Vc::upcast(FullContextTransition::new(self.shared_module_context()))
793798
}
794799

800+
#[turbo_tasks::function]
801+
fn rsc_transition(self: Vc<Self>, runtime: NextRuntime) -> Vc<Box<dyn Transition>> {
802+
Vc::upcast(RSCTransition::new(self, runtime))
803+
}
804+
795805
#[turbo_tasks::function]
796806
async fn edge_ssr_module_context(self: Vc<Self>) -> Result<Vc<ModuleAssetContext>> {
797807
let transitions = [
@@ -970,6 +980,7 @@ impl AppProject {
970980
&self,
971981
endpoint: Vc<AppEndpoint>,
972982
rsc_entry: ResolvedVc<Box<dyn Module>>,
983+
server_action_loader_module: ResolvedVc<Box<dyn Module>>,
973984
client_shared_entries: Vc<EvaluatableAssets>,
974985
has_layout_segments: bool,
975986
) -> Result<Vc<BaseAndFullModuleGraph>> {
@@ -987,7 +998,8 @@ impl AppProject {
987998
// Implements layout segment optimization to compute a graph "chain" for each layout
988999
// segment
9891000
async move {
990-
let rsc_entry_chunk_group = ChunkGroupEntry::Entry(vec![rsc_entry]);
1001+
let rsc_entry_chunk_group =
1002+
ChunkGroupEntry::Entry(vec![server_action_loader_module, rsc_entry]);
9911003

9921004
let mut graphs = vec![];
9931005
let mut visited_modules = if has_layout_segments {
@@ -1292,6 +1304,32 @@ impl AppEndpoint {
12921304
Ok(app_entry)
12931305
}
12941306

1307+
#[turbo_tasks::function]
1308+
async fn server_action_loader_module(self: Vc<Self>) -> Result<Vc<Box<dyn Module>>> {
1309+
let this = self.await?;
1310+
let app_entry = self.app_endpoint_entry().await?;
1311+
let runtime = app_entry.config.await?.runtime.unwrap_or_default();
1312+
1313+
let module_context = match runtime {
1314+
NextRuntime::Edge => this.app_project.edge_rsc_module_context(),
1315+
NextRuntime::NodeJs => this.app_project.rsc_module_context(),
1316+
};
1317+
1318+
Ok(module_context
1319+
.process(
1320+
Vc::upcast(FileSource::new_with_query(
1321+
virtual_next_js_template_path(
1322+
this.app_project.project().project_path().owned().await?,
1323+
"turbopack-action-loader.js",
1324+
)
1325+
.await?,
1326+
RcStr::from(format!("?{}", this.page)),
1327+
)),
1328+
ReferenceType::Undefined,
1329+
)
1330+
.module())
1331+
}
1332+
12951333
#[turbo_tasks::function]
12961334
async fn output(self: Vc<Self>) -> Result<Vc<AppEndpointOutput>> {
12971335
let this = self.await?;
@@ -1344,11 +1382,14 @@ impl AppEndpoint {
13441382

13451383
let is_app_page = matches!(this.ty, AppEndpointType::Page { .. });
13461384

1385+
let server_action_loader = self.server_action_loader_module();
1386+
13471387
let module_graphs = this
13481388
.app_project
13491389
.app_module_graphs(
13501390
self,
13511391
*rsc_entry,
1392+
server_action_loader,
13521393
// We only need the client runtime entries for pages not for Route Handlers
13531394
if is_app_page {
13541395
this.app_project.client_runtime_entries()
@@ -1549,41 +1590,26 @@ impl AppEndpoint {
15491590
}
15501591
}
15511592

1552-
let actions = ServerActionsGraphs::new(*module_graphs.base, per_page_module_graph)
1553-
.get_server_actions_for_endpoint(
1554-
*rsc_entry,
1555-
match runtime {
1556-
NextRuntime::Edge => Vc::upcast(this.app_project.edge_rsc_module_context()),
1557-
NextRuntime::NodeJs => Vc::upcast(this.app_project.rsc_module_context()),
1558-
},
1559-
);
1560-
1561-
let server_action_manifest = create_server_actions_manifest(
1562-
actions,
1563-
project.project_path().owned().await?,
1564-
node_root.clone(),
1565-
app_entry.original_name.clone(),
1566-
runtime,
1567-
match runtime {
1568-
NextRuntime::Edge => Vc::upcast(this.app_project.edge_rsc_module_context()),
1569-
NextRuntime::NodeJs => Vc::upcast(this.app_project.rsc_module_context()),
1570-
},
1571-
*module_graphs.full,
1572-
this.app_project
1573-
.project()
1574-
.runtime_chunking_context(process_client_assets, runtime),
1575-
)
1576-
.await?;
15771593
if emit_rsc_manifests {
1578-
server_assets.insert(server_action_manifest.manifest);
1594+
server_assets.insert(
1595+
create_server_actions_manifest(
1596+
self.server_action_loader_module(),
1597+
node_root.clone(),
1598+
app_entry.original_name.clone(),
1599+
runtime,
1600+
*module_graphs.full,
1601+
this.app_project
1602+
.project()
1603+
.runtime_chunking_context(process_client_assets, runtime),
1604+
)
1605+
.to_resolved()
1606+
.await?,
1607+
);
15791608
}
15801609

1581-
let server_action_manifest_loader = server_action_manifest.loader;
1582-
15831610
let app_entry_chunks = self
15841611
.app_entry_chunks(
15851612
*client_references,
1586-
*server_action_manifest_loader,
15871613
server_path.clone(),
15881614
process_client_assets,
15891615
*module_graphs.full,
@@ -1876,7 +1902,6 @@ impl AppEndpoint {
18761902
async fn app_entry_chunks(
18771903
self: Vc<Self>,
18781904
client_references: Vc<ClientReferenceGraphResult>,
1879-
server_action_manifest_loader: ResolvedVc<Box<dyn EvaluatableAsset>>,
18801905
server_path: FileSystemPath,
18811906
process_client_assets: bool,
18821907
module_graph: Vc<ModuleGraph>,
@@ -1885,34 +1910,23 @@ impl AppEndpoint {
18851910
let project = this.app_project.project();
18861911
let app_entry = self.app_endpoint_entry().await?;
18871912
let runtime = app_entry.config.await?.runtime.unwrap_or_default();
1913+
let server_action_loader = self.server_action_loader_module().to_resolved().await?;
18881914

18891915
let chunking_context = project.runtime_chunking_context(process_client_assets, runtime);
18901916

18911917
Ok(match runtime {
1892-
NextRuntime::Edge => {
1893-
let chunk_group1 = chunking_context.chunk_group(
1894-
server_action_manifest_loader.ident(),
1895-
ChunkGroup::Shared(ResolvedVc::upcast(server_action_manifest_loader)),
1896-
module_graph,
1897-
AvailabilityInfo::root(),
1898-
);
1899-
1900-
let chunk_group2_assets = chunking_context.evaluated_chunk_group_assets(
1901-
app_entry.rsc_entry.ident(),
1902-
ChunkGroup::Entry(vec![app_entry.rsc_entry]),
1903-
module_graph,
1904-
chunk_group1.await?.availability_info,
1905-
);
1906-
1907-
chunk_group1
1908-
.output_assets_with_referenced()
1909-
.concatenate(chunk_group2_assets)
1910-
}
1918+
NextRuntime::Edge => chunking_context.evaluated_chunk_group_assets(
1919+
app_entry.rsc_entry.ident(),
1920+
ChunkGroup::Entry(vec![server_action_loader, app_entry.rsc_entry]),
1921+
module_graph,
1922+
AvailabilityInfo::root(),
1923+
),
19111924
NextRuntime::NodeJs => {
19121925
async {
19131926
let mut current_chunk_group = ChunkGroupResult::empty_resolved();
19141927

1915-
let entry_chunk_group = ChunkGroup::Entry(vec![app_entry.rsc_entry]);
1928+
let entry_chunk_group =
1929+
ChunkGroup::Entry(vec![server_action_loader, app_entry.rsc_entry]);
19161930

19171931
let chunk_group_info = module_graph.chunk_group_info();
19181932

@@ -1991,20 +2005,6 @@ impl AppEndpoint {
19912005
.await?;
19922006
}
19932007

1994-
{
1995-
let chunk_group = chunking_context.chunk_group(
1996-
server_action_manifest_loader.ident(),
1997-
ChunkGroup::Shared(ResolvedVc::upcast(server_action_manifest_loader)),
1998-
module_graph,
1999-
current_chunk_group.await?.availability_info,
2000-
);
2001-
2002-
current_chunk_group = current_chunk_group
2003-
.concatenate(chunk_group)
2004-
.to_resolved()
2005-
.await?;
2006-
}
2007-
20082008
let current_referenced_assets = current_chunk_group.referenced_assets();
20092009
let chunk_group = current_chunk_group.await?;
20102010
let current_availability_info = chunk_group.availability_info;
@@ -2186,7 +2186,10 @@ impl Endpoint for AppEndpoint {
21862186
async fn entries(self: Vc<Self>) -> Result<Vc<GraphEntries>> {
21872187
let this = self.await?;
21882188
Ok(Vc::cell(vec![
2189-
ChunkGroupEntry::Entry(vec![self.app_endpoint_entry().await?.rsc_entry]),
2189+
ChunkGroupEntry::Entry(vec![
2190+
self.server_action_loader_module().to_resolved().await?,
2191+
self.app_endpoint_entry().await?.rsc_entry,
2192+
]),
21902193
ChunkGroupEntry::Entry(
21912194
this.app_project
21922195
.client_runtime_entries()
@@ -2199,56 +2202,58 @@ impl Endpoint for AppEndpoint {
21992202
]))
22002203
}
22012204

2202-
#[turbo_tasks::function]
2203-
async fn additional_entries(
2204-
self: Vc<Self>,
2205-
graph: Vc<ModuleGraph>,
2206-
) -> Result<Vc<GraphEntries>> {
2207-
let this = self.await?;
2208-
let app_entry = self.app_endpoint_entry().await?;
2209-
let rsc_entry = app_entry.rsc_entry;
2210-
let runtime = app_entry.config.await?.runtime.unwrap_or_default();
2211-
2212-
let actions = ServerActionsGraphs::new(
2213-
graph,
2214-
*this.app_project.project().per_page_module_graph().await?,
2215-
)
2216-
.get_server_actions_for_endpoint(
2217-
*rsc_entry,
2218-
match runtime {
2219-
NextRuntime::Edge => Vc::upcast(this.app_project.edge_rsc_module_context()),
2220-
NextRuntime::NodeJs => Vc::upcast(this.app_project.rsc_module_context()),
2221-
},
2222-
);
2223-
2224-
let server_actions_loader = ResolvedVc::upcast(
2225-
build_server_actions_loader(
2226-
this.app_project.project().project_path().owned().await?,
2227-
app_entry.original_name.clone(),
2228-
actions,
2229-
match runtime {
2230-
NextRuntime::Edge => Vc::upcast(this.app_project.edge_rsc_module_context()),
2231-
NextRuntime::NodeJs => Vc::upcast(this.app_project.rsc_module_context()),
2232-
},
2233-
)
2234-
.to_resolved()
2235-
.await?,
2236-
);
2237-
2238-
Ok(Vc::cell(vec![ChunkGroupEntry::Entry(vec![
2239-
server_actions_loader,
2240-
])]))
2241-
}
2205+
// #[turbo_tasks::function]
2206+
// async fn additional_entries(
2207+
// self: Vc<Self>,
2208+
// graph: Vc<ModuleGraph>,
2209+
// ) -> Result<Vc<GraphEntries>> {
2210+
// let this = self.await?;
2211+
// let app_entry = self.app_endpoint_entry().await?;
2212+
// let rsc_entry = app_entry.rsc_entry;
2213+
// let runtime = app_entry.config.await?.runtime.unwrap_or_default();
2214+
2215+
// let actions = ServerActionsGraphs::new(
2216+
// graph,
2217+
// *this.app_project.project().per_page_module_graph().await?,
2218+
// )
2219+
// .get_server_actions_for_endpoint(
2220+
// *rsc_entry,
2221+
// match runtime {
2222+
// NextRuntime::Edge => Vc::upcast(this.app_project.edge_rsc_module_context()),
2223+
// NextRuntime::NodeJs => Vc::upcast(this.app_project.rsc_module_context()),
2224+
// },
2225+
// );
2226+
2227+
// let server_actions_loader = ResolvedVc::upcast(
2228+
// build_server_actions_loader(
2229+
// this.app_project.project().project_path().owned().await?,
2230+
// app_entry.original_name.clone(),
2231+
// actions,
2232+
// match runtime {
2233+
// NextRuntime::Edge => Vc::upcast(this.app_project.edge_rsc_module_context()),
2234+
// NextRuntime::NodeJs => Vc::upcast(this.app_project.rsc_module_context()),
2235+
// },
2236+
// )
2237+
// .to_resolved()
2238+
// .await?,
2239+
// );
2240+
2241+
// Ok(Vc::cell(vec![ChunkGroupEntry::Entry(vec![
2242+
// server_actions_loader,
2243+
// ])]))
2244+
// }
22422245

22432246
#[turbo_tasks::function]
22442247
async fn module_graphs(self: Vc<Self>) -> Result<Vc<ModuleGraphs>> {
22452248
let this = self.await?;
22462249
let app_entry = self.app_endpoint_entry().await?;
2250+
let server_action_loader = self.server_action_loader_module();
22472251
let module_graphs = this
22482252
.app_project
22492253
.app_module_graphs(
22502254
self,
22512255
*app_entry.rsc_entry,
2256+
server_action_loader,
22522257
this.app_project.client_runtime_entries(),
22532258
matches!(this.ty, AppEndpointType::Page { .. }),
22542259
)

0 commit comments

Comments
 (0)