Turbopack: switch to a single client components entrypoint (#59352)

### What?

switch turbopack to use a single client components entrypoint for all
client components on a page for development. This aligns it with the
webpack behavior.

### Why?

compiling a separate entrypoint for every client component is pretty
expensive in regards of compilation, chunking, code generation, file
writing and number of requests.

### Turbopack Changes

* https://github.com/vercel/turbo/pull/6713 <!-- Tobias Koppers - use
real emojis -->
* https://github.com/vercel/turbo/pull/6728 <!-- Tobias Koppers - fix
order of reverse topologic iteration -->


Closes PACK-2115
This commit is contained in:
Tobias Koppers 2023-12-08 08:24:08 +01:00 committed by GitHub
parent f7b9843b92
commit 26b8caaa29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 399 additions and 93 deletions

68
Cargo.lock generated
View file

@ -322,7 +322,7 @@ dependencies = [
[[package]]
name = "auto-hash-map"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"serde",
"smallvec",
@ -3549,7 +3549,7 @@ dependencies = [
[[package]]
name = "node-file-trace"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"serde",
@ -7678,7 +7678,7 @@ dependencies = [
[[package]]
name = "turbo-tasks"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-trait",
@ -7710,7 +7710,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-build"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"cargo-lock",
@ -7722,7 +7722,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-bytes"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"bytes",
@ -7737,7 +7737,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-env"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"dotenvs",
@ -7751,7 +7751,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-fetch"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"indexmap 1.9.3",
@ -7768,7 +7768,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-fs"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"auto-hash-map",
@ -7799,7 +7799,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-hash"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"base16",
"hex",
@ -7811,7 +7811,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-macros"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@ -7825,7 +7825,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-macros-shared"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"proc-macro2",
"quote",
@ -7835,7 +7835,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-malloc"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"mimalloc",
]
@ -7843,7 +7843,7 @@ dependencies = [
[[package]]
name = "turbo-tasks-memory"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"auto-hash-map",
@ -7868,7 +7868,7 @@ dependencies = [
[[package]]
name = "turbopack"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-recursion",
@ -7900,7 +7900,7 @@ dependencies = [
[[package]]
name = "turbopack-binding"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"auto-hash-map",
"mdxjs",
@ -7941,7 +7941,7 @@ dependencies = [
[[package]]
name = "turbopack-build"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"indexmap 1.9.3",
@ -7965,7 +7965,7 @@ dependencies = [
[[package]]
name = "turbopack-cli-utils"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"clap 4.4.2",
@ -7983,7 +7983,7 @@ dependencies = [
[[package]]
name = "turbopack-core"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-recursion",
@ -8013,7 +8013,7 @@ dependencies = [
[[package]]
name = "turbopack-css"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-trait",
@ -8040,7 +8040,7 @@ dependencies = [
[[package]]
name = "turbopack-dev"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"indexmap 1.9.3",
@ -8064,7 +8064,7 @@ dependencies = [
[[package]]
name = "turbopack-dev-server"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-compression",
@ -8101,7 +8101,7 @@ dependencies = [
[[package]]
name = "turbopack-ecmascript"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-trait",
@ -8135,7 +8135,7 @@ dependencies = [
[[package]]
name = "turbopack-ecmascript-hmr-protocol"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"serde",
"serde_json",
@ -8146,7 +8146,7 @@ dependencies = [
[[package]]
name = "turbopack-ecmascript-plugins"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-trait",
@ -8169,7 +8169,7 @@ dependencies = [
[[package]]
name = "turbopack-ecmascript-runtime"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"indoc",
@ -8186,7 +8186,7 @@ dependencies = [
[[package]]
name = "turbopack-env"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"indexmap 1.9.3",
@ -8202,7 +8202,7 @@ dependencies = [
[[package]]
name = "turbopack-image"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"base64 0.21.4",
@ -8222,7 +8222,7 @@ dependencies = [
[[package]]
name = "turbopack-json"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"serde",
@ -8237,7 +8237,7 @@ dependencies = [
[[package]]
name = "turbopack-mdx"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"mdxjs",
@ -8252,7 +8252,7 @@ dependencies = [
[[package]]
name = "turbopack-node"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"async-stream",
@ -8287,7 +8287,7 @@ dependencies = [
[[package]]
name = "turbopack-static"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"serde",
@ -8303,7 +8303,7 @@ dependencies = [
[[package]]
name = "turbopack-swc-utils"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"swc_core",
"turbo-tasks",
@ -8314,7 +8314,7 @@ dependencies = [
[[package]]
name = "turbopack-trace-utils"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"crossbeam-channel",
@ -8329,7 +8329,7 @@ dependencies = [
[[package]]
name = "turbopack-wasm"
version = "0.1.0"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231206.4#f99cd2550f9f4c2b89e173532cc72797d613b82f"
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-231207.2#d168d850a3eda771477886171f2014a0c167aab6"
dependencies = [
"anyhow",
"indexmap 1.9.3",

View file

@ -43,11 +43,11 @@ swc_core = { version = "0.86.81", features = [
testing = { version = "0.35.11" }
# Turbo crates
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-231206.4" }
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-231207.2" }
# [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros..
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-231206.4" }
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-231207.2" }
# [TODO]: need to refactor embed_directory! macro usage in next-core
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-231206.4" }
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-231207.2" }
# General Deps

View file

@ -625,6 +625,7 @@ impl AppEndpoint {
};
let client_references_chunks = get_app_client_references_chunks(
app_entry.rsc_entry.ident(),
client_reference_types,
this.app_project.project().client_chunking_context(),
ssr_chunking_context,
@ -637,7 +638,7 @@ impl AppEndpoint {
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");
.context("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());
@ -651,15 +652,15 @@ impl AppEndpoint {
.map(|chunk| chunk.ident().path())
.try_join()
.await?;
let mut entry_client_chunks_paths: Vec<_> = entry_client_chunks_paths
let mut entry_client_chunks_paths = entry_client_chunks_paths
.iter()
.map(|path| {
client_relative_path_ref
Ok(client_relative_path_ref
.get_path_to(path)
.expect("asset path should be inside client root")
.to_string()
.context("asset path should be inside client root")?
.to_string())
})
.collect();
.collect::<anyhow::Result<Vec<_>>>()?;
entry_client_chunks_paths.extend(client_shared_chunks_paths.iter().cloned());
let app_build_manifest = AppBuildManifest {
@ -997,7 +998,7 @@ impl AppEndpoint {
server_path
.await?
.get_path_to(&*rsc_chunk.ident().path().await?)
.expect("RSC chunk path should be within app paths manifest directory")
.context("RSC chunk path should be within app paths manifest directory")?
.to_string(),
)?;
server_assets.push(app_paths_manifest_output);

View file

@ -35,6 +35,7 @@ use turbopack_binding::{
core::{
asset::Asset,
environment::ServerAddr,
ident::AssetIdent,
issue::{handle_issues, IssueReporter, IssueSeverity},
output::{OutputAsset, OutputAssets},
virtual_fs::VirtualFileSystem,
@ -309,6 +310,7 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
// APP CLIENT REFERENCES CHUNKING
let app_client_references_chunks = get_app_client_references_chunks(
AssetIdent::from_path(project_root.join("next-client-components.js".to_string())),
app_client_reference_tys,
client_chunking_context,
// TODO(WEB-1824): add edge support

View file

@ -1,4 +1,7 @@
use std::fmt::Write;
use std::{
fmt::Write,
mem::{replace, take},
};
use anyhow::Result;
use async_recursion::async_recursion;
@ -384,13 +387,9 @@ impl LoaderTreeBuilder {
"[{segment}, {{",
segment = StringifyJs(segment)
)?;
// add parallel_routes
for (key, &parallel_route) in parallel_routes.iter() {
write!(self.loader_tree_code, "{key}: ", key = StringifyJs(key))?;
self.walk_tree(parallel_route, false).await?;
writeln!(self.loader_tree_code, ",")?;
}
writeln!(self.loader_tree_code, "}}, {{")?;
// Components need to be referenced first
let temp_loader_tree_code = take(&mut self.loader_tree_code);
// add components
let Components {
page,
@ -403,17 +402,28 @@ impl LoaderTreeBuilder {
metadata,
route: _,
} = &*components.await?;
self.write_component(ComponentType::Layout, *layout).await?;
self.write_component(ComponentType::Page, *page).await?;
self.write_component(ComponentType::DefaultPage, *default)
.await?;
self.write_component(ComponentType::Error, *error).await?;
self.write_component(ComponentType::Layout, *layout).await?;
self.write_component(ComponentType::Loading, *loading)
.await?;
self.write_component(ComponentType::Template, *template)
.await?;
self.write_component(ComponentType::NotFound, *not_found)
.await?;
let components_code = replace(&mut self.loader_tree_code, temp_loader_tree_code);
// add parallel_routes
for (key, &parallel_route) in parallel_routes.iter() {
write!(self.loader_tree_code, "{key}: ", key = StringifyJs(key))?;
self.walk_tree(parallel_route, false).await?;
writeln!(self.loader_tree_code, ",")?;
}
writeln!(self.loader_tree_code, "}}, {{")?;
self.loader_tree_code += &components_code;
// Ensure global metadata being written only once at the root level
// Otherwise child pages will have redundant metadata

View file

@ -6,10 +6,11 @@ use turbo_tasks::{
debug::ValueDebugFormat, trace::TraceRawVcs, TryFlatJoinIterExt, TryJoinIterExt, Vc,
};
use turbopack_binding::turbopack::{
core::{chunk::ChunkingContextExt, module::Module, output::OutputAssets},
core::{chunk::ChunkingContextExt, ident::AssetIdent, module::Module, output::OutputAssets},
ecmascript::chunk::EcmascriptChunkingContext,
};
use super::include_modules_module::IncludeModulesModule;
use crate::next_client_reference::{ClientReferenceType, ClientReferenceTypes};
/// Contains the chunks corresponding to a client reference.
@ -32,50 +33,116 @@ pub struct ClientReferencesChunks(IndexMap<ClientReferenceType, ClientReferenceC
/// type needs to load.
#[turbo_tasks::function]
pub async fn get_app_client_references_chunks(
base_ident: Vc<AssetIdent>,
app_client_reference_types: Vc<ClientReferenceTypes>,
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
) -> Result<Vc<ClientReferencesChunks>> {
async move {
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
.await?
.iter()
.map(|client_reference_ty| async move {
Ok((
*client_reference_ty,
match client_reference_ty {
// TODO Reconsider this. Maybe it need to be true in production.
let separate_chunk_group_per_client_reference = false;
let app_client_reference_types = app_client_reference_types.await?;
if separate_chunk_group_per_client_reference {
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
.iter()
.map(|client_reference_ty| async move {
Ok((
*client_reference_ty,
match client_reference_ty {
ClientReferenceType::EcmascriptClientReference(
ecmascript_client_reference,
) => {
let ecmascript_client_reference_ref =
ecmascript_client_reference.await?;
ClientReferenceChunks {
client_chunks: client_chunking_context.root_chunk_group(
Vc::upcast(ecmascript_client_reference_ref.client_module),
),
ssr_chunks: ssr_chunking_context.root_chunk_group(Vc::upcast(
ecmascript_client_reference_ref.ssr_module,
)),
}
}
ClientReferenceType::CssClientReference(css_client_reference) => {
let css_client_reference_ref = css_client_reference.await?;
ClientReferenceChunks {
client_chunks: client_chunking_context.root_chunk_group(
Vc::upcast(css_client_reference_ref.client_module),
),
ssr_chunks: OutputAssets::empty(),
}
}
},
))
})
.try_join()
.await?
.into_iter()
.collect();
Ok(Vc::cell(app_client_references_chunks))
} else {
let ssr_modules = app_client_reference_types
.iter()
.map(|client_reference_ty| async move {
Ok(match client_reference_ty {
ClientReferenceType::EcmascriptClientReference(
ecmascript_client_reference,
) => {
let ecmascript_client_reference_ref =
ecmascript_client_reference.await?;
ClientReferenceChunks {
client_chunks: client_chunking_context.root_chunk_group(
Vc::upcast(ecmascript_client_reference_ref.client_module),
),
ssr_chunks: ssr_chunking_context.root_chunk_group(Vc::upcast(
ecmascript_client_reference_ref.ssr_module,
)),
}
Some(Vc::upcast(ecmascript_client_reference_ref.ssr_module))
}
_ => None,
})
})
.try_flat_join()
.await?;
let ssr_entry_module = IncludeModulesModule::new(
base_ident.with_modifier(Vc::cell("client modules ssr".to_string())),
Vc::cell(ssr_modules),
);
let client_modules = app_client_reference_types
.iter()
.map(|client_reference_ty| async move {
Ok(match client_reference_ty {
ClientReferenceType::EcmascriptClientReference(
ecmascript_client_reference,
) => {
let ecmascript_client_reference_ref =
ecmascript_client_reference.await?;
Vc::upcast(ecmascript_client_reference_ref.client_module)
}
ClientReferenceType::CssClientReference(css_client_reference) => {
let css_client_reference_ref = css_client_reference.await?;
ClientReferenceChunks {
client_chunks: client_chunking_context.root_chunk_group(
Vc::upcast(css_client_reference_ref.client_module),
),
ssr_chunks: OutputAssets::empty(),
}
Vc::upcast(css_client_reference_ref.client_module)
}
},
))
})
.try_join()
.await?
.into_iter()
.collect();
})
})
.try_join()
.await?;
let client_entry_module = IncludeModulesModule::new(
base_ident.with_modifier(Vc::cell("client modules".to_string())),
Vc::cell(client_modules),
);
let global_entry_module = ClientReferenceChunks {
client_chunks: {
let _span = tracing::info_span!("client side rendering").entered();
client_chunking_context.root_chunk_group(Vc::upcast(client_entry_module))
},
ssr_chunks: {
let _span = tracing::info_span!("server side rendering").entered();
ssr_chunking_context.root_chunk_group(Vc::upcast(ssr_entry_module))
},
};
Ok(Vc::cell(app_client_references_chunks))
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
.iter()
.map(move |&client_reference_ty| (client_reference_ty, global_entry_module.clone()))
.collect();
Ok(Vc::cell(app_client_references_chunks))
}
}
.instrument(tracing::info_span!("process client references"))
.await

View file

@ -0,0 +1,183 @@
use anyhow::{Context, Result};
use turbo_tasks::{TryJoinIterExt, ValueToString, Vc};
use turbopack_binding::turbopack::{
core::{
asset::{Asset, AssetContent},
chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkableModuleReference, ChunkingContext},
ident::AssetIdent,
module::{Module, Modules},
reference::{ModuleReference, ModuleReferences},
resolve::ModuleResolveResult,
},
ecmascript::chunk::{
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable,
EcmascriptChunkType, EcmascriptChunkingContext, EcmascriptExports,
},
};
/// A virtual module that references other modules, but doesn't do anything at
/// runtime. It can be used to include modules into a chunk.
#[turbo_tasks::value]
pub struct IncludeModulesModule {
ident: Vc<AssetIdent>,
modules: Vc<Modules>,
}
#[turbo_tasks::value_impl]
impl IncludeModulesModule {
#[turbo_tasks::function]
pub fn new(ident: Vc<AssetIdent>, modules: Vc<Modules>) -> Vc<Self> {
Self { ident, modules }.cell()
}
}
impl Asset for IncludeModulesModule {
fn content(self: Vc<Self>) -> Vc<AssetContent> {
todo!("IncludeModulesModule doesn't implement content()")
}
}
#[turbo_tasks::value_impl]
impl Module for IncludeModulesModule {
#[turbo_tasks::function]
fn ident(&self) -> Vc<AssetIdent> {
self.ident
}
#[turbo_tasks::function]
async fn references(&self) -> Result<Vc<ModuleReferences>> {
Ok(Vc::cell(
self.modules
.await?
.iter()
.map(|&module| async move {
Ok(Vc::upcast(
IncludedModuleReference::new(module).resolve().await?,
))
})
.try_join()
.await?,
))
}
}
#[turbo_tasks::value_impl]
impl EcmascriptChunkPlaceable for IncludeModulesModule {
#[turbo_tasks::function]
fn get_exports(self: Vc<Self>) -> Vc<EcmascriptExports> {
EcmascriptExports::None.cell()
}
#[turbo_tasks::function]
fn is_marked_as_side_effect_free(self: Vc<Self>) -> Vc<bool> {
Vc::cell(true)
}
}
#[turbo_tasks::value_impl]
impl ChunkableModule for IncludeModulesModule {
#[turbo_tasks::function]
async fn as_chunk_item(
self: Vc<Self>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
) -> Result<Vc<Box<dyn ChunkItem>>> {
let chunking_context =
Vc::try_resolve_downcast::<Box<dyn EcmascriptChunkingContext>>(chunking_context)
.await?
.context(
"chunking context must impl EcmascriptChunkingContext to use \
EcmascriptClientReferenceProxyModule",
)?;
Ok(Vc::upcast(
IncludeModulesChunkItem {
module: self,
chunking_context,
}
.cell(),
))
}
}
/// The chunk item for [`IncludeModulesModule`].
#[turbo_tasks::value]
struct IncludeModulesChunkItem {
module: Vc<IncludeModulesModule>,
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
}
#[turbo_tasks::value_impl]
impl ChunkItem for IncludeModulesChunkItem {
#[turbo_tasks::function]
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
Vc::upcast(self.chunking_context)
}
#[turbo_tasks::function]
fn asset_ident(&self) -> Vc<AssetIdent> {
self.module.ident()
}
#[turbo_tasks::function]
fn references(&self) -> Vc<ModuleReferences> {
self.module.references()
}
#[turbo_tasks::function]
fn ty(&self) -> Vc<Box<dyn ChunkType>> {
Vc::upcast(Vc::<EcmascriptChunkType>::default())
}
#[turbo_tasks::function]
fn module(&self) -> Vc<Box<dyn Module>> {
Vc::upcast(self.module)
}
}
#[turbo_tasks::value_impl]
impl EcmascriptChunkItem for IncludeModulesChunkItem {
#[turbo_tasks::function]
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
self.chunking_context
}
#[turbo_tasks::function]
fn content(&self) -> Vc<EcmascriptChunkItemContent> {
EcmascriptChunkItemContent {
..Default::default()
}
.cell()
}
}
/// A module reference that references a module that is references from the
/// [`IncludeModulesModule`].
#[turbo_tasks::value]
pub struct IncludedModuleReference {
pub module: Vc<Box<dyn Module>>,
}
#[turbo_tasks::value_impl]
impl IncludedModuleReference {
#[turbo_tasks::function]
pub fn new(module: Vc<Box<dyn Module>>) -> Vc<Self> {
IncludedModuleReference { module }.cell()
}
}
#[turbo_tasks::value_impl]
impl ValueToString for IncludedModuleReference {
#[turbo_tasks::function]
fn to_string(&self) -> Vc<String> {
Vc::cell("module".to_string())
}
}
#[turbo_tasks::value_impl]
impl ModuleReference for IncludedModuleReference {
#[turbo_tasks::function]
async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
Ok(ModuleResolveResult::module(self.module).cell())
}
}
#[turbo_tasks::value_impl]
impl ChunkableModuleReference for IncludedModuleReference {}

View file

@ -3,6 +3,7 @@ pub mod app_client_shared_chunks;
pub mod app_entry;
pub mod app_page_entry;
pub mod app_route_entry;
pub mod include_modules_module;
pub mod metadata;
use std::{

View file

@ -195,7 +195,7 @@
"@types/ws": "8.2.0",
"@vercel/ncc": "0.34.0",
"@vercel/nft": "0.24.4",
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231206.4",
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231207.2",
"acorn": "8.5.0",
"amphtml-validator": "1.0.35",
"anser": "1.4.9",

View file

@ -1077,8 +1077,8 @@ importers:
specifier: 0.24.4
version: 0.24.4
'@vercel/turbopack-ecmascript-runtime':
specifier: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231206.4
version: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231206.4(react-refresh@0.12.0)(webpack@5.86.0)'
specifier: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231207.2
version: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231207.2(react-refresh@0.12.0)(webpack@5.86.0)'
acorn:
specifier: 8.5.0
version: 8.5.0
@ -24647,9 +24647,9 @@ packages:
/zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
'@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231206.4(react-refresh@0.12.0)(webpack@5.86.0)':
resolution: {registry: https://registry.npmjs.org/, tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231206.4}
id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231206.4'
'@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231207.2(react-refresh@0.12.0)(webpack@5.86.0)':
resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231207.2}
id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-231207.2'
name: '@vercel/turbopack-ecmascript-runtime'
version: 0.0.0
dependencies:

View file

@ -0,0 +1,5 @@
@layer default {
h2 {
color: black;
}
}

View file

@ -0,0 +1,7 @@
'use client'
import './layout-input.css'
export default function InputText() {
return <input />
}

View file

@ -1,5 +1,11 @@
import './index.css'
import InputText from './layout-input'
export default function Layout({ children }) {
return <div>{children}</div>
return (
<div>
{children}
<InputText />
</div>
)
}

View file

@ -0,0 +1,7 @@
@layer default;
@layer default {
h2 {
color: red;
}
}

View file

@ -1,9 +1,11 @@
import './page-index.css'
import InputText from './input'
export default function Home() {
return (
<div>
<h1>Hello</h1>
<h2>Hello</h2>
<InputText />
</div>
)

View file

@ -306,6 +306,11 @@ createNextDescribe(
`window.getComputedStyle(document.querySelector('h1')).color`
)
).toBe('rgb(255, 0, 0)')
expect(
await browser.eval(
`window.getComputedStyle(document.querySelector('h2')).color`
)
).toBe('rgb(255, 0, 0)')
})
})
@ -321,6 +326,11 @@ createNextDescribe(
`window.getComputedStyle(document.querySelector('h1')).color`
)
).toBe('rgb(255, 0, 0)')
expect(
await browser.eval(
`window.getComputedStyle(document.querySelector('h2')).color`
)
).toBe('rgb(255, 0, 0)')
try {
await next.patchFile(
@ -338,6 +348,11 @@ createNextDescribe(
`window.getComputedStyle(document.querySelector('h1')).color`
)
).toBe('rgb(255, 0, 0)')
expect(
await browser.eval(
`window.getComputedStyle(document.querySelector('h2')).color`
)
).toBe('rgb(255, 0, 0)')
} finally {
await next.patchFile(filePath, origContent)
}

View file

@ -2359,7 +2359,6 @@
"app dir - css HMR should support HMR for CSS imports in client components",
"app dir - css HMR should support HMR for CSS imports in server components",
"app dir - css HMR should support HMR with sass/scss",
"app dir - css Suspensey CSS should suspend on CSS imports if its slow on client navigation",
"app dir - css css support client components should support css modules inside client components",
"app dir - css css support client components should support css modules inside client page",
"app dir - css css support client layouts should support css modules inside client layouts",
@ -2392,6 +2391,7 @@
],
"failed": [
"app dir - css HMR should not create duplicate link tags during HMR",
"app dir - css Suspensey CSS should suspend on CSS imports if its slow on client navigation",
"app dir - css css support chunks should bundle css resources into chunks",
"app dir - css css support multiple entries should deduplicate styles on the module level",
"app dir - css css support multiple entries should only include the same style once in the flight data",
@ -7387,11 +7387,11 @@
},
"test/integration/css/test/css-modules.test.js": {
"passed": [
"CSS Modules Composes Ordering Development Mode should have correct color on index page (on hover)",
"CSS Modules Composes Ordering Development Mode should have correct color on index page (on load)",
"Ordering with Global CSS and Modules (dev) should not execute scripts in any order"
],
"failed": [
"CSS Modules Composes Ordering Development Mode should have correct color on index page (on hover)",
"CSS Modules Composes Ordering Development Mode should have correct color on index page (on load)",
"Basic CSS Modules Ordering Development Mode should have correct color on index page (on hover)",
"Basic CSS Modules Ordering Development Mode should have correct color on index page (on load)",
"Basic CSS Modules Ordering Development Mode should have correct color on index page (on nav)",