8000 Turbopack: scope hoisting by mischnic · Pull Request #79459 · vercel/next.js · GitHub
[go: up one dir, main page]

Skip to content

Turbopack: scope hoisting #79459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 96 commits into from
Jun 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
a8e483e
Always set exports on reference
mischnic May 21, 2025
db43184
__turbopack_esm_other__
mischnic May 5, 2025
622e91f
Support additional ids in runtime
mischnic May 9, 2025
9f5ec8c
MergeableModule
mischnic May 8, 2025
b758d0f
MergedModules Graph visitor
mischnic Apr 29, 2025
85a3e9c
MergedModules Graph visitor
mischnic May 8, 2025
30dd2d9
Convert modules in chunk_group_content
mischnic May 9, 2025
3edd980
codegen
mischnic Apr 29, 2025
bd8d448
MergedEcmascriptModule
mischnic May 8, 2025
6ba12cb
Emit additional id list
mischnic May 9, 2025
238a41a
MergedModules per group bitmaps
mischnic May 12, 2025
ba76647
MergedModules global bitmap
mischnic May 13, 2025
3b3e9bf
Don't merge CJS exports
mischnic May 13, 2025
6c9b27e
MergedModules
mischnic May 13, 2025
2040b1d
fixups
mischnic May 13, 2025
2f2b782
fixup codegen
mischnic May 13, 2025
391d9c1
WIP MergedModules externals
mischnic May 13, 2025
0add007
fixup codegen
mischnic May 13, 2025
8c3bff7
fixup MergedEcmascriptModule
mischnic May 13, 2025
cf4f14b
fixup MergedModules infinite loop
mischnic May 14, 2025
42a0102
fix namespace imports inside merged group
mischnic May 14, 2025
72fc1e5
Implement __turbopack_esm_other__ differently
mischnic May 14, 2025
adde1d8
fixup codegen
mischnic May 14, 2025
2768749
Require missing exports
mischnic May 14, 2025
77fcb19
Don't expose all modules
mischnic May 21, 2025
a3502aa
cleanup
mischnic May 15, 2025
e0db749
Async modules aren't mergeable
mischnic May 15, 2025
cac9439
Revert "undo merged_modules"
mischnic May 21, 2025
2e17750
Expose namespace imported modules
mischnic May 16, 2025
87d6726
Support ImportedNamespace reexports
mischnic May 16, 2025
7ece57d
Fix reexports from unmerged modules
mischnic May 16, 2025
3e1537a
Fix reexport-star inside of merged group
mischnic May 16, 2025
d3ce316
Fix local renaming when they are exports
mischnic May 16, 2025
53ab7ab
Fix local renaming when they are exports
mischnic May 19, 2025
a5cb93c
Refactor: MergeableModule.is_mergable
mischnic May 19, 2025
ccc416c
Correct order of merged and unmerged references
mischnic May 19, 2025
5a7c0b0
Fix list traversal with cycles
mischnic May 20, 2025
72d0949
Ensure correct ordering
mischnic May 21, 2025
a542254
Multiple entries in a merged group
mischnic May 21, 2025
2cecad4
Correctly compute merged group entries
mischnic May 21, 2025
7a0feb2
Expose entry modules (assuming they are required)
mischnic May 21, 2025
28b937b
is_module_merging_enabled on context, not in dev
mischnic May 21, 2025
8da956c
Turbopack: remove dead code in runtime
mischnic May 23, 2025
4ff4017
Fix module exposing due to splitting
mischnic May 23, 2025
d828952
Proper stubs for snapshots
mischnic May 23, 2025
85b802f
Add turbopackScopeHoisting setting
mischnic May 27, 2025
37a060b
Cleanup
mischnic May 27, 2025
cb013b7
Cleanup
mischnic May 28, 2025
b637d25
Fix availability info
mischnic May 30, 2025
2ac1f5d
Improve error message
mischnic Jun 2, 2025
9e83b34
Review feedback
mischnic Jun 2, 2025
3fa4839
Don't mutate the globals in the cell
mischnic Jun 2, 2025
e3705f2
Fix reexport cycle hanging
mischnic Jun 3, 2025
e8da2b9
Change chunk item id to first entry instead
mischnic Jun 3, 2025
6ef74d2
Review feedback: reverse map once
mischnic Jun 3, 2025
4fa7678
Refactor ScopeHoistingContext
mischnic Jun 3, 2025
< 8000 div class="select-menu-item-text"> ecfb63a
Clone globals only if necessary
mischnic Jun 3, 2025
d50aecf
Emit correct comments for scope hoisted modules
mischnic Jun 3, 2025
c989d80
Better BytePos module encoding
mischnic Jun 4, 2025
cc28898
Emit correct source maps for scope hoisted modules
mischnic Jun 4, 2025
6b1139b
Add test case
mischnic Jun 5, 2025
bdb716c
Include syntaxcontext in preserved_exports
mischnic Jun 5, 2025
50083ee
Fix variable renaming again
mischnic Jun 5, 2025
96aa75c
Cleanup
mischnic Jun 6, 2025
eeb5248
Insert comments for merged modules
mischnic Jun 10, 2025
cda71f8
Update snapshots
mischnic Jun 10, 2025
6e8e874
Make AST merging more efficient
mischnic Jun 10, 2025
4cf49bf
Add snapshot test for input source maps
mischnic Jun 10, 2025
1982472
Bump swc_sourcemap
mischnic Jun 11, 2025
3c1bb40
Fix original source maps for scope hoisting
mischnic Jun 11, 2025
874d165
Cleanup
mischnic Jun 11, 2025
60df2f1
Improve tests
mischnic Jun 11, 2025
41d2637
MergeableModuleExposure
mischnic Jun 12, 2025
bc31ac2
Less cloning
mischnic Jun 13, 2025
5a29c4a
Cleanup
mischnic Jun 13, 2025
79012be
Cleanup
mischnic Jun 13, 2025
2a89ff3
Dedupe imports
mischnic Jun 13, 2025
5ea90bb
Leverage `ResolvedVc::deref_vec`
mischnic Jun 14, 2025
4222ece
feedback: clarify MergeableModuleExposure
mischnic Jun 17, 2025
5f0edc2
feedback: disallow scope hoisting in dev
mischnic Jun 17, 2025
84d4afc
feedback: rewrite condition
mischnic Jun 17, 2025
ffa9c11
feedback: typos
mischnic Jun 17, 2025
d3b821d
feedback: get rid of clone
mischnic Jun 17, 2025
027a091
feedback
mischnic Jun 17, 2025
c34168d
feedback: simplify
mischnic Jun 17, 2025
4f1b34e
feedback: derive Ord instead
mischnic Jun 17, 2025
d7f3a89
feedback: relax memory ordering
mischnic Jun 18, 2025
20316e4
Fixup name matching in prod
mischnic Jun 18, 2025
554d7ee
feedback: rename to modules_header_width
mischnic Jun 18, 2025
92d6027
add some more comments
mischnic Jun 18, 2025
771595e
Fix reexports of CJS
mischnic Jun 23, 2025
2f3d88d
Add test for CJS reexport
mischnic Jun 23, 2025
cffab22
Less strict Module/Script handling
mischnic Jun 23, 2025
1b3d69a
Snapshot tests: setting for prod chunking
mischnic Jun 24, 2025
5aef9b0
Fix shared chunk handling for merged modules
mischnic Jun 24, 2025
d3f5c0e
feedback: consistently use mergeable set instead of downcast
mischnic Jun 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10000
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ test/e2e/async-modules/amp-validator-wasm.js
/turbopack/crates/next-transform-dynamic/tests
/turbopack/crates/turbopack-tests/tests/execution/turbopack/basic/error/input/broken.js
/turbopack/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs
/turbopack/crates/turbopack-tests/tests/snapshot/source_maps/*
/turbopack/crates/turbopack-tests/tests/**/output*
/turbopack/crates/turbopack-tests/tests/**/static

5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ smallvec = { version = "1.13.1", features = [
"union",
"const_new",
] }
swc_sourcemap = "9.2.2"
swc_sourcemap = "9.3.2"
strsim = "0.11.1"
shrink-to-fit = "0.2.10"
syn = "2.0.100"
Expand Down
5 changes: 5 additions & 0 deletions crates/next-api/src/project.rs
10000
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,7 @@ impl Project {
self.next_config().turbo_minify(self.next_mode()),
self.next_config().client_source_maps(self.next_mode()),
self.no_mangling(),
self.next_config().turbo_scope_hoisting(self.next_mode()),
))
}

Expand All @@ -1038,6 +1039,7 @@ impl Project {
self.next_config().turbo_minify(self.next_mode()),
self.next_config().server_source_maps(),
self.no_mangling(),
self.next_config().turbo_scope_hoisting(self.next_mode()),
)
} else {
get_server_chunking_context(
Expand All @@ -1050,6 +1052,7 @@ impl Project {
self.next_config().turbo_minify(self.next_mode()),
self.next_config().server_source_maps(),
self.no_mangling(),
self.next_config().turbo_scope_hoisting(self.next_mode()),
)
})
}
Expand All @@ -1072,6 +1075,7 @@ impl Project {
self.next_config().turbo_minify(self.next_mode()),
self.next_config().server_source_maps(),
self.no_mangling(),
self.next_config().turbo_scope_hoisting(self.next_mode()),
)
} else {
get_edge_chunking_context(
Expand All @@ -1084,6 +1088,7 @@ impl Project {
self.next_config().turbo_minify(self.next_mode()),
self.next_config().server_source_maps(),
self.no_mangling(),
self.next_config().turbo_scope_hoisting(self.next_mode()),
)
})
}
Expand Down
37 changes: 20 additions & 17 deletions crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ pub async fn get_client_chunking_context(
minify: Vc<bool>,
source_maps: Vc<bool>,
no_mangling: Vc<bool>,
scope_hoisting: Vc<bool>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let next_mode = mode.await?;
let mut builder = BrowserChunkingContext::builder(
Expand Down Expand Up @@ -471,23 +472,25 @@ pub async fn get_client_chunking_context(
if next_mode.is_development() {
builder = builder.hot_module_replacement().use_file_source_map_uris();
} else {
builder = builder.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 50_000,
max_chunk_count_per_group: 40,
max_merge_chunk_size: 200_000,
..Default::def 97AE ault()
},
);
builder = builder.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder.use_content_hashing(ContentHashing::Direct { length: 16 })
builder = builder
.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 50_000,
max_chunk_count_per_group: 40,
max_merge_chunk_size: 200_000,
..Default::default()
},
)
.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.use_content_hashing(ContentHashing::Direct { length: 16 })
.module_merging(*scope_hoisting.await?);
}

Ok(Vc::upcast(builder.build()))
Expand Down
10 changes: 10 additions & 0 deletions crates/next-core/src/next_config.rs
741A
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ pub struct ExperimentalConfig {
turbopack_persistent_caching: Option<bool>,
turbopack_source_maps: Option<bool>,
turbopack_tree_shaking: Option<bool>,
turbopack_scope_hoisting: Option<bool>,
// Whether to enable the global-not-found convention
global_not_found: Option<bool>,
/// Defaults to false in development mode, true in production mode.
Expand Down Expand Up @@ -1593,6 +1594,15 @@ impl NextConfig {
))
}

#[turbo_tasks::function]
pub async fn turbo_scope_hoisting(&self, mode: Vc<NextMode>) -> Result<Vc<bool>> {
Ok(Vc::cell(match *mode.await? {
// Ignore configuration in development mode to not break HMR
NextMode::Development => false,
NextMode::Build => self.experimental.turbopack_scope_hoisting.unwrap_or(true),
}))
}

#[turbo_tasks::function]
pub async fn client_source_maps(&self, _mode: Vc<NextMode>) -> Result<Vc<bool>> {
// Temporarily always enable client source maps as tests regress.
Expand Down
62 changes: 34 additions & 28 deletions crates/next-core/src/next_edge/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ pub async fn get_edge_chunking_context_with_client_assets(
turbo_minify: Vc<bool>,
turbo_source_maps: Vc<bool>,
no_mangling: Vc<bool>,
scope_hoisting: Vc<bool>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let output_root = node_root.join(rcstr!("server/edge")).to_resolved().await?;
let next_mode = mode.await?;
Expand Down Expand Up @@ -258,20 +259,22 @@ pub async fn get_edge_chunking_context_with_client_assets(
.module_id_strategy(module_id_strategy);

if !next_mode.is_development() {
builder = builder.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
..Default::default()
},
);
builder = builder.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder
.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
..Default::default()
},
)
.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.module_merging(*scope_hoisting.await?);
}

Ok(Vc::upcast(builder.build()))
Expand All @@ -288,6 +291,7 @@ pub async fn get_edge_chunking_context(
turbo_minify: Vc<bool>,
turbo_source_maps: Vc<bool>,
no_mangling: Vc<bool>,
scope_hoisting: Vc<bool>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let output_root = node_root.join(rcstr!("server/edge")).to_resolved().await?;
let next_mode = mode.await?;
Expand Down Expand Up @@ -321,20 +325,22 @@ pub async fn get_edge_chunking_context(
.module_id_strategy(module_id_strategy);

if !next_mode.is_development() {
builder = builder.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
..Default::default()
},
);
builder = builder.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder
.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
..Default::default()
},
)
.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.module_merging(*scope_hoisting.await?);
}

Ok(Vc::upcast(builder.build()))
Expand Down
70 changes: 38 additions & 32 deletions crates/next-core/src/next_server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@ pub async fn get_server_chunking_context_with_client_assets(
turbo_minify: Vc<bool>,
turbo_source_maps: Vc<bool>,
no_mangling: Vc<bool>,
scope_hoisting: Vc<bool>,
) -> Result<Vc<NodeJsChunkingContext>> {
let next_mode = mode.await?;
// TODO(alexkirsz) This should return a trait that can be implemented by the
Expand Down Expand Up @@ -1037,22 +1038,24 @@ pub async fn get_server_chunking_context_with_client_assets(
if next_mode.is_development() {
builder = builder.use_file_source_map_uris();
} else {
builder = builder.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
max_chunk_count_per_group: 100,
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder
.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
max_chunk_count_per_group: 100,
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.module_merging(*scope_hoisting.await?);
}

Ok(builder.build())
Expand All @@ -1069,6 +1072,7 @@ pub async fn get_server_chunking_context(
turbo_minify: Vc<bool>,
turbo_source_maps: Vc<bool>,
no_mangling: Vc<bool>,
scope_hoisting: Vc<bool>,
) -> Result<Vc<NodeJsChunkingContext>> {
let next_mode = mode.await?;
// TODO(alexkirsz) This should return a trait that can be implemented by the
Expand Down Expand Up @@ -1108,22 +1112,24 @@ pub async fn get_server_chunking_context(
if next_mode.is_development() {
builder = builder.use_file_source_map_uris()
} else {
builder = builder.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
max_chunk_count_per_group: 100,
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
);
builder = builder
.chunking_config(
Vc::<EcmascriptChunkType>::default().to_resolved().await?,
ChunkingConfig {
min_chunk_size: 20_000,
max_chunk_count_per_group: 100,
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.chunking_config(
Vc::<CssChunkType>::default().to_resolved().await?,
ChunkingConfig {
max_merge_chunk_size: 100_000,
..Default::default()
},
)
.module_merging(*scope_hoisting.await?);
}

Ok(builder.build())
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/server/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ export const configSchema: zod.ZodType<NextConfig> = z.lazy(() =>
turbopackSourceMaps: z.boolean().optional(),
turbopackTreeShaking: z.boolean().optional(),
turbopackRemoveUnusedExports: z.boolean().optional(),
turbopackScopeHoisting: z.boolean().optional(),
optimizePackageImports: z.array(z.string()).optional(),
optimizeServerReact: z.boolean().optional(),
clientTraceMetadata: z.array(z.string()).optional(),
Expand Down
5 changes: 5 additions & 0 deletions packages/next/src/server/config-shared.ts
5A9A
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,11 @@ export interface ExperimentalConfig {
*/
turbopackMinify?: boolean

/**
* Enable scope hoisting. Defaults to true in build mode. Always disabled in development mode.
*/
turbopackScopeHoisting?: boolean

/**
* Enable persistent caching for the turbopack dev server and build.
*/
Expand Down
Loading
Loading
0