Skip to content

Commit 9a9698a

Browse files
committed
Turbopack: only enable nested async availability in production
This avoid the combinations of paths problem in dev since this creates a lot of output files in development (every chunk group has a register chunk group chunk in dev, and we don't have commons chunk optimization in dev)
1 parent 338f5ad commit 9a9698a

File tree

77 files changed

+246
-123
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+246
-123
lines changed

crates/next-core/src/next_client/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ pub async fn get_client_chunking_context(
510510
},
511511
)
512512
.use_content_hashing(ContentHashing::Direct { length: 16 })
513+
.nested_async_availability(true)
513514
.module_merging(*scope_hoisting.await?);
514515
}
515516

crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,10 @@ impl EcmascriptChunkItem for EcmascriptClientReferenceProxyChunkItem {
329329
fn content_with_async_module_info(
330330
&self,
331331
async_module_info: Option<Vc<AsyncModuleInfo>>,
332+
estimated: bool,
332333
) -> Vc<EcmascriptChunkItemContent> {
333334
self.inner_chunk_item
334-
.content_with_async_module_info(async_module_info)
335+
.content_with_async_module_info(async_module_info, estimated)
335336
}
336337
}
337338

turbopack/crates/turbopack-browser/src/chunking_context.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ impl BrowserChunkingContextBuilder {
101101
self
102102
}
103103

104+
pub fn nested_async_availability(mut self, enable_nested_async_availability: bool) -> Self {
105+
self.chunking_context.enable_nested_async_availability = enable_nested_async_availability;
106+
self
107+
}
108+
104109
pub fn module_merging(mut self, enable_module_merging: bool) -> Self {
105110
self.chunking_context.enable_module_merging = enable_module_merging;
106111
self
@@ -261,6 +266,8 @@ pub struct BrowserChunkingContext {
261266
enable_hot_module_replacement: bool,
262267
/// Enable tracing for this chunking
263268
enable_tracing: bool,
269+
/// Enable nested async availability for this chunking
270+
enable_nested_async_availability: bool,
264271
/// Enable module merging
265272
enable_module_merging: bool,
266273
/// Enable dynamic chunk content loading.
@@ -320,6 +327,7 @@ impl BrowserChunkingContext {
320327
asset_base_paths: Default::default(),
321328
enable_hot_module_replacement: false,
322329
enable_tracing: false,
330+
enable_nested_async_availability: false,
323331
enable_module_merging: false,
324332
enable_dynamic_chunk_content_loading: false,
325333
debug_ids: false,
@@ -626,6 +634,11 @@ impl ChunkingContext for BrowserChunkingContext {
626634
Vc::cell(self.enable_tracing)
627635
}
628636

637+
#[turbo_tasks::function]
638+
fn is_nested_async_availability_enabled(&self) -> Vc<bool> {
639+
Vc::cell(self.enable_nested_async_availability)
640+
}
641+
629642
#[turbo_tasks::function]
630643
fn is_module_merging_enabled(&self) -> Vc<bool> {
631644
Vc::cell(self.enable_module_merging)

turbopack/crates/turbopack-cli/src/build/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ async fn build_internal(
367367
},
368368
)
369369
.use_content_hashing(ContentHashing::Direct { length: 16 })
370+
.nested_async_availability(true)
370371
.module_merging(scope_hoist);
371372
}
372373
}

turbopack/crates/turbopack-cli/src/dev/web_entry_source.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub async fn get_client_chunking_context(
5555
.hot_module_replacement()
5656
.source_map_source_type(SourceMapSourceType::AbsoluteFileUri)
5757
.dynamic_chunk_content_loading(true)
58+
.nested_async_availability(true)
5859
.build(),
5960
))
6061
}

turbopack/crates/turbopack-core/src/chunk/availability_info.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ bitfield! {
1010
#[derive(Clone, Copy, Default, TaskInput, TraceRawVcs, NonLocalValue, Serialize, Deserialize, PartialEq, Eq, Hash)]
1111
pub struct AvailabilityFlags(u8);
1212
impl Debug;
13+
pub is_in_of_async_module, set_is_in_of_async_module: 0;
1314
}
1415

1516
#[derive(
@@ -62,6 +63,19 @@ impl AvailabilityInfo {
6263
})
6364
}
6465

66+
pub fn in_async_module(self) -> Self {
67+
let mut flags = self.flags;
68+
flags.set_is_in_of_async_module(true);
69+
Self {
70+
flags,
71+
available_modules: self.available_modules,
72+
}
73+
}
74+
75+
pub fn is_in_async_module(&self) -> bool {
76+
self.flags.is_in_of_async_module()
77+
}
78+
6579
pub async fn ident(&self) -> Result<Option<RcStr>> {
6680
Ok(if let Some(available_modules) = self.available_modules {
6781
Some(available_modules.hash().await?.to_string().into())

turbopack/crates/turbopack-core/src/chunk/chunk_group.rs

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub async fn make_chunk_group(
5454
*chunking_context.environment().chunk_loading().await?,
5555
ChunkLoading::Edge
5656
);
57+
let is_nested_async_availability_enabled = *chunking_context
58+
.is_nested_async_availability_enabled()
59+
.await?;
5760
let should_trace = *chunking_context.is_tracing_enabled().await?;
5861
let should_merge_modules = *chunking_context.is_module_merging_enabled().await?;
5962
let batching_config = chunking_context.batching_config();
@@ -63,15 +66,17 @@ pub async fn make_chunk_group(
6366
batch_groups,
6467
async_modules,
6568
traced_modules,
66-
availability_info,
69+
availability_info: new_availability_info,
6770
} = chunk_group_content(
6871
module_graph,
6972
chunk_group_entries.clone(),
70-
availability_info,
71-
can_split_async,
72-
should_trace,
73-
should_merge_modules,
74-
batching_config,
73+
ChunkGroupContentOptions {
74+
availability_info,
75+
can_split_async,
76+
should_trace,
77+
should_merge_modules,
78+
batching_config,
79+
},
7580
)
7681
.await?;
7782

@@ -109,11 +114,17 @@ pub async fn make_chunk_group(
109114
.await?;
110115

111116
// Insert async chunk loaders for every referenced async module
117+
let async_availability_info =
118+
if is_nested_async_availability_enabled || !availability_info.is_in_async_module() {
119+
new_availability_info.in_async_module()
120+
} else {
121+
availability_info
122+
};
112123
let async_loaders = async_modules
113124
.into_iter()
114125
.map(async |module| {
115126
chunking_context
116-
.async_loader_chunk_item(*module, module_graph, availability_info)
127+
.async_loader_chunk_item(*module, module_graph, async_availability_info)
117128
.to_resolved()
118129
.await
119130
})
@@ -153,7 +164,7 @@ pub async fn make_chunk_group(
153164
chunks,
154165
referenced_output_assets,
155166
references: ResolvedVc::upcast_vec(async_loaders),
156-
availability_info,
167+
availability_info: new_availability_info,
157168
})
158169
}
159170

@@ -180,16 +191,43 @@ pub async fn references_to_output_assets(
180191
.cell())
181192
}
182193

194+
pub struct ChunkGroupContentOptions {
195+
/// The availability info of the chunk group
196+
pub availability_info: AvailabilityInfo,
197+
/// Whether async modules can be split into separate chunks
198+
pub can_split_async: bool,
199+
/// Whether traced modules should be collected
200+
pub should_trace: bool,
201+
/// Whether module merging is enabled
202+
pub should_merge_modules: bool,
203+
/// The batching config to use
204+
pub batching_config: Vc<BatchingConfig>,
205+
}
206+
207+
/// Computes the content of a chunk group.
208+
///
209+
/// ### Parameters:
210+
/// - module_graph: the module graph
211+
/// - chunk_group_entries: the entries of the chunk group
212+
/// - availability_info: the availability info of the chunk group
213+
/// - can_split_async: indicates whether async modules can be split into separate chunks
214+
/// - update_availability_info: indicates whether to return a new availability info which includes
215+
/// all chunk items.
216+
/// - should_trace: indicates whether traced modules should be collected
217+
/// - should_merge_modules: indicates whether module merging is enabled
218+
/// - batching_config: the batching config to use
183219
pub async fn chunk_group_content(
184220
module_graph: Vc<ModuleGraph>,
185221
chunk_group_entries: impl IntoIterator<
186222
IntoIter = impl Iterator<Item = ResolvedVc<Box<dyn Module>>> + Send,
187223
> + Send,
188-
availability_info: AvailabilityInfo,
189-
can_split_async: bool,
190-
should_trace: bool,
191-
should_merge_modules: bool,
192-
batching_config: Vc<BatchingConfig>,
224+
ChunkGroupContentOptions {
225+
availability_info,
226+
can_split_async,
227+
should_trace,
228+
should_merge_modules,
229+
batching_config,
230+
}: ChunkGroupContentOptions,
193231
) -> Result<ChunkGroupContent> {
194232
let module_batches_graph = module_graph.module_batches(batching_config).await?;
195233

turbopack/crates/turbopack-core/src/chunk/chunking_context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,15 @@ pub trait ChunkingContext {
339339
Vc::cell(false)
340340
}
341341

342+
/// Whether async modules should create an new availability boundary and therefore nested async
343+
/// modules include less modules. Enabling this will lead to better optimized async chunks,
344+
/// but it will require to compute all possible paths in the application, which might lead to
345+
/// many combinations.
346+
#[turbo_tasks::function]
347+
fn is_nested_async_availability_enabled(self: Vc<Self>) -> Vc<bool> {
348+
Vc::cell(false)
349+
}
350+
342351
/// Whether to use `MergeableModule` to merge modules if possible.
343352
#[turbo_tasks::function]
344353
fn is_module_merging_enabled(self: Vc<Self>) -> Vc<bool> {

turbopack/crates/turbopack-ecmascript/src/async_chunk/chunk_item.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use indoc::formatdoc;
33
use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc};
44
use turbopack_core::{
55
chunk::{
6-
ChunkData, ChunkItem, ChunkType, ChunkingContext, ChunkingContextExt, ChunksData,
7-
ModuleChunkItemIdExt,
6+
AsyncModuleInfo, ChunkData, ChunkItem, ChunkType, ChunkingContext, ChunkingContextExt,
7+
ChunksData, ModuleChunkItemIdExt,
88
},
99
ident::AssetIdent,
1010
module::Module,
@@ -149,6 +149,30 @@ impl EcmascriptChunkItem for AsyncLoaderChunkItem {
149149
}
150150
.cell())
151151
}
152+
153+
#[turbo_tasks::function]
154+
fn content_with_async_module_info(
155+
self: Vc<Self>,
156+
_async_module_info: Option<Vc<AsyncModuleInfo>>,
157+
estimated: bool,
158+
) -> Vc<EcmascriptChunkItemContent> {
159+
if estimated {
160+
let code = formatdoc! {
161+
r#"
162+
{TURBOPACK_EXPORT_VALUE}((parentImport) => {{
163+
return Promise.all([].map((chunk) => {TURBOPACK_LOAD}(chunk))).then(() => {{}});
164+
}});
165+
"#,
166+
};
167+
EcmascriptChunkItemContent {
168+
inner_code: code.into(),
169+
..Default::default()
170+
}
171+
.cell()
172+
} else {
173+
self.content()
174+
}
175+
}
152176
}
153177

154178
#[turbo_tasks::value_impl]
@@ -168,9 +192,26 @@ impl ChunkItem for AsyncLoaderChunkItem {
168192

169193
#[turbo_tasks::function]
170194
async fn content_ident(self: Vc<Self>) -> Result<Vc<AssetIdent>> {
171-
let ident = self.module().ident();
195+
let mut ident = self.module().ident();
196+
197+
let this = self.await?;
198+
199+
let nested_async_availability = this
200+
.chunking_context
201+
.is_nested_async_availability_enabled()
202+
.await?;
203+
204+
let availability_ident = if *nested_async_availability {
205+
Some(self.chunks_data().hash().await?.to_string().into())
206+
} else {
207+
this.module.await?.availability_info.ident().await?
208+
};
209+
210+
if let Some(availability_ident) = availability_ident {
211+
ident = ident.with_modifier(availability_ident)
212+
}
172213

173-
Ok(ident.with_modifier(self.chunks_data().hash().await?.to_string().into()))
214+
Ok(ident)
174215
}
175216

176217
#[turbo_tasks::function]

turbopack/crates/turbopack-ecmascript/src/chunk/chunk_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl ChunkType for EcmascriptChunkType {
6767
};
6868
Ok(Vc::cell(
6969
chunk_item
70-
.content_with_async_module_info(async_module_info)
70+
.content_with_async_module_info(async_module_info, true)
7171
.await
7272
.map_or(0, |content| round_chunk_item_size(content.inner_code.len())),
7373
))

0 commit comments

Comments
 (0)