Skip to content

Commit

Permalink
fix rsc endpoint content
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Sep 15, 2023
1 parent 2456045 commit 0487394
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 80 deletions.
164 changes: 86 additions & 78 deletions packages/next-swc/crates/next-api/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,19 @@ impl AppEndpoint {
async fn output(self: Vc<Self>) -> Result<Vc<AppEndpointOutput>> {
let this = self.await?;

let (app_entry, ty) = match this.ty {
AppEndpointType::Page { ty: _, loader_tree } => {
(self.app_page_entry(loader_tree), "page")
}
let (app_entry, ty, ssr_and_client) = match this.ty {
AppEndpointType::Page { ty, loader_tree } => (
self.app_page_entry(loader_tree),
"page",
matches!(ty, AppPageEndpointType::Html),
),
// NOTE(alexkirsz) For routes, technically, a lot of the following code is not needed,
// as we know we won't have any client references. However, for now, for simplicity's
// sake, we just do the same thing as for pages.
AppEndpointType::Route { path } => (self.app_route_entry(path), "route"),
AppEndpointType::Metadata { metadata } => (self.app_metadata_entry(metadata), "route"),
AppEndpointType::Route { path } => (self.app_route_entry(path), "route", false),
AppEndpointType::Metadata { metadata } => {
(self.app_metadata_entry(metadata), "route", false)
}
};

let node_root = this.app_project.project().node_root();
Expand Down Expand Up @@ -562,82 +566,86 @@ impl AppEndpoint {
.entry(Vc::upcast(app_entry.rsc_entry))
.await?;

let client_references_chunks = get_app_client_references_chunks(
client_reference_types,
this.app_project.project().client_chunking_context(),
this.app_project.project().ssr_chunking_context(),
);
let client_references_chunks_ref = client_references_chunks.await?;

let mut entry_client_chunks = vec![];
// TODO(alexkirsz) In which manifest does this go?
let mut entry_ssr_chunks = vec![];
for client_reference in app_entry_client_references.iter() {
let client_reference_chunks = client_references_chunks_ref
.get(client_reference.ty())
.expect("client reference should have corresponding chunks");
entry_client_chunks
.extend(client_reference_chunks.client_chunks.await?.iter().copied());
entry_ssr_chunks.extend(client_reference_chunks.ssr_chunks.await?.iter().copied());
}
if ssr_and_client {
let client_references_chunks = get_app_client_references_chunks(
client_reference_types,
this.app_project.project().client_chunking_context(),
this.app_project.project().ssr_chunking_context(),
);
let client_references_chunks_ref = client_references_chunks.await?;

let mut entry_client_chunks = vec![];
// TODO(alexkirsz) In which manifest does this go?
let mut entry_ssr_chunks = vec![];
for client_reference in app_entry_client_references.iter() {
let client_reference_chunks = client_references_chunks_ref
.get(client_reference.ty())
.expect("client reference should have corresponding chunks");
entry_client_chunks
.extend(client_reference_chunks.client_chunks.await?.iter().copied());
entry_ssr_chunks.extend(client_reference_chunks.ssr_chunks.await?.iter().copied());
}

client_assets.extend(entry_client_chunks.iter().copied());
server_assets.extend(entry_ssr_chunks.iter().copied());
client_assets.extend(entry_client_chunks.iter().copied());
server_assets.extend(entry_ssr_chunks.iter().copied());

let entry_client_chunks_paths = entry_client_chunks
.iter()
.map(|chunk| chunk.ident().path())
.try_join()
.await?;
let mut entry_client_chunks_paths: Vec<_> = entry_client_chunks_paths
.iter()
.map(|path| {
client_relative_path_ref
.get_path_to(path)
.expect("asset path should be inside client root")
.to_string()
})
.collect();
entry_client_chunks_paths.extend(client_shared_chunks_paths.iter().cloned());
let entry_client_chunks_paths = entry_client_chunks
.iter()
.map(|chunk| chunk.ident().path())
.try_join()
.await?;
let mut entry_client_chunks_paths: Vec<_> = entry_client_chunks_paths
.iter()
.map(|path| {
client_relative_path_ref
.get_path_to(path)
.expect("asset path should be inside client root")
.to_string()
})
.collect();
entry_client_chunks_paths.extend(client_shared_chunks_paths.iter().cloned());

let app_build_manifest = AppBuildManifest {
pages: [(app_entry.original_name.clone(), entry_client_chunks_paths)]
.into_iter()
.collect(),
};
let manifest_path_prefix = get_asset_prefix_from_pathname(&app_entry.pathname);
let app_build_manifest_output = Vc::upcast(VirtualOutputAsset::new(
node_root.join(format!(
"server/app{manifest_path_prefix}/{ty}/app-build-manifest.json",
)),
AssetContent::file(
File::from(serde_json::to_string_pretty(&app_build_manifest)?).into(),
),
));
server_assets.push(app_build_manifest_output);
let app_build_manifest = AppBuildManifest {
pages: [(app_entry.original_name.clone(), entry_client_chunks_paths)]
.into_iter()
.collect(),
};
let manifest_path_prefix = get_asset_prefix_from_pathname(&app_entry.pathname);
let app_build_manifest_output = Vc::upcast(VirtualOutputAsset::new(
node_root.join(format!(
"server/app{manifest_path_prefix}/{ty}/app-build-manifest.json",
)),
AssetContent::file(
File::from(serde_json::to_string_pretty(&app_build_manifest)?).into(),
),
));
server_assets.push(app_build_manifest_output);

let build_manifest = BuildManifest {
root_main_files: client_shared_chunks_paths,
..Default::default()
};
let build_manifest_output = Vc::upcast(VirtualOutputAsset::new(
node_root.join(format!(
"server/app{manifest_path_prefix}/{ty}/build-manifest.json",
)),
AssetContent::file(File::from(serde_json::to_string_pretty(&build_manifest)?).into()),
));
server_assets.push(build_manifest_output);

let entry_manifest = ClientReferenceManifest::build_output(
node_root,
client_relative_path,
app_entry.original_name.clone(),
client_references,
client_references_chunks,
this.app_project.project().client_chunking_context(),
Vc::upcast(this.app_project.project().ssr_chunking_context()),
);
server_assets.push(entry_manifest);
let build_manifest = BuildManifest {
root_main_files: client_shared_chunks_paths,
..Default::default()
};
let build_manifest_output = Vc::upcast(VirtualOutputAsset::new(
node_root.join(format!(
"server/app{manifest_path_prefix}/{ty}/build-manifest.json",
)),
AssetContent::file(
File::from(serde_json::to_string_pretty(&build_manifest)?).into(),
),
));
server_assets.push(build_manifest_output);

let entry_manifest = ClientReferenceManifest::build_output(
node_root,
client_relative_path,
app_entry.original_name.clone(),
client_references,
client_references_chunks,
this.app_project.project().client_chunking_context(),
Vc::upcast(this.app_project.project().ssr_chunking_context()),
);
server_assets.push(entry_manifest);
}

fn create_app_paths_manifest(
node_root: Vc<FileSystemPath>,
Expand Down
3 changes: 1 addition & 2 deletions test/development/basic/next-rs-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,7 @@ describe('next.rs api', () => {
file: 'app/app/client.ts',
content: '"use client";\nexport default () => <div>hello world2</div>',
expectedUpdate: '/app/app/client.ts',
// TODO(sokra) this should be false, not sure why it's true
expectedServerSideChange: true,
expectedServerSideChange: false,
},
{
name: 'server-side change on a app page',
Expand Down

0 comments on commit 0487394

Please sign in to comment.