When using `nextConfig.i18n`, then static files for `404.html` and
`500.html` were added multiple times to the list.
These duplicate entries in `outputs.staticFiles` ended up causing race
conditions in the Vercel adapter because the same output file path was
written concurrently by multiple file operations.
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Signed commits
- This repository requires verified commit signatures on protected
branches.
- If this pull request is blocked for unsigned commits, re-sign the
commits and force-push the branch.
- A `Signed-off-by` line in the commit message is not enough.
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
Fixup for #95357
`.handler()` is used by adapters
but `.default()` (=`internalHandler`) is the legacy entrypoint and used
by the non-adapter setup
Also needs https://github.com/vercel/vercel/pull/16944
- One of them tests that an error is thrown. Don't run the deployment
test there
- The other tests are still broken when deployed, but we will fix that
separately
`output=export` and `output=standalone` don't use adapters.
But for `supportsImmutableAssets`, you really want the adapter to get
all necessary data.
Disable immutable assets for now in this case. Once `output=export` runs
the adapter (as it should), we can remove this override again
The vercel CLI's trace format is 99% the same as the Next.js
`.next/trace` format. Except that it's using UUID as span ids, instead
of numbers.
1. Run `pnpm next internal trace
.vercel/output/diagnostics/cli_traces.json`
2. Profit
<img width="1434" height="265" alt="Bildschirmfoto 2026-07-06 um 15 23
02"
src="https://github.com/user-attachments/assets/b1cc0a8d-a1d3-4135-884b-e3050514853f"
/>
Node.js Middleware was inheriting the wrong parent span (and behaved
differently compared to Edge runtime Middleware)
`Middleware.execute` and `BaseServer.handleRequest` should be sibling
spans (depending on context, both are root spans). Previously
`BaseServer.handleRequest` had a child span `Middleware.execute`
Depends on https://github.com/vercel/next.js/pull/95357 to make the
direct entrypoint test pass
#94306 fixes this for pages, but middleware was still broken when
deployed via adapters
Coming from https://github.com/getsentry/sentry-javascript/issues/21713
Now the instrumentation test suite takes 11m to run in deployment mode
though....
Thus far, it wasn't possible to use `require()` in a template file with
Webpack.
But I needed to add a `if(NEXT_RUNTIME !== "edge") { const x =
require("../../something"); }`
Turbopack doesn't do any regex rewrite hacks, so this just worked
This computes the implementation hash of a given `use cache`:
- it includes the module containing the `use cache` function, plus all transitive imports of that module (including externals via NFT)
- what does it hash
- for bundled code, it hashes the generated code (so including any AST transforms, inlined env vars, etc)
- for NFTd files, it hashes the file content on disk
- So this is basically equivalent to hashing the generated JS chunks, except that it's scoped to only what the given actions module uses
- (so notably, if you have multiple use cache functions in a given file, then they will all have the same hash)
<br/>
- [x] Gate behind experimental flag
- [x] Only compute hash for `use cache` functions, not all server actions
- [ ] `final_read_hint` is a problem. Some chunk items are now codgened twice, so it recomputes the AST
- [x] disable for dev for now
- [ ] Measure perf impact
```jsonc
// .next/server/server-reference-manifest.json
{
"node": {
"806f4954cfbb75404a19d6d405065ed9059cc0cab2": {
"workers": {
"app/rsc/page": {
"moduleId": "[project]/bench/app-router-server/.next-internal/server/app/rsc/page/actions.js { ACTIONS_MODULE0 => \"[project]/bench/app-router-server/app/rsc/logic.js [app-rsc] (ecmascript)\" } [app-rsc] (server actions loader, ecmascript)",
"async": false,
"exportedName": "$$RSC_SERVER_CACHE_0",
"filename": "bench/app-router-server/app/rsc/logic.js",
"codeHash": "413e394d9597b35df12828a6a7fd6363" // <------------
}
},
"filename": "bench/app-router-server/app/rsc/logic.js",
"exportedName": "$$RSC_SERVER_CACHE_0"
}
},
"edge": {},
"encryptionKey": "jOF2TbpNLjp2oOhl3VPBwGE7luodnei9clJPq/gaYQo="
}
```
We already switched to 128 bit hashes for many operations, these were
still using 64 bit hashes.
- make `hash_xxh3_hash128` return `u128`, just like `hash_xxh3_hash64`
returns a `u64`
- Make `Code::source_code_hash` return a u128
**View diff without whitespace**
When using adapters, throwing a JS error from a App Route Handler didn't
set the OTEL status code correctly.
It was doing this:
```js
try {
tracer.trace(() => {
try {
// handle...
} finally {
setOtel();
}
});
} catch(e){
send500();
}
```
Which I now changed to
```js
tracer.trace(() => {
try {
// handle...
} catch(e){
send500();
} finally {
setOtel();
}
});
```
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Signed commits
- This repository requires verified commit signatures on protected
branches.
- If this pull request is blocked for unsigned commits, re-sign the
commits and force-push the branch.
- A `Signed-off-by` line in the commit message is not enough.
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
---------
Co-authored-by: Will Binns-Smith <[email protected]>
`repoRoot` shouldn't be `outputFileTracingRoot`. The user can configure
that to arbitrary values, which shouldn't change the adapter output.
The adapter now uses `NextConfigComplete.repoRoot` instead of
`outputFileTracingRoot`.
Closes NEXT-4942
The logic is slightly less brittle now.
It broke because of this rename in v0.35:
```
@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node
->
@img/sharp-darwin-arm64/lib/sharp-darwin-arm64-0.35.1.node
```
**View diff without whitespace**
1. RSC requests weren't properly handled
2. The mismatch on getServerSideProps is actually fine (depends on
whatever invokes the handler)
**Ignore whitespace changes when viewing the diff**
This fixes some of the failures (particularly the ones where a 500
returned from an App API route showed up as status:200 in OTEL).
But the newly added tests have more failures that I skipped for now
1. Missing `setStatus` call
2. Attribute handling was too early, before `sendResponse` was called:
https://github.com/vercel/next.js/blob/6f4d94ac889db3d23a77847ec4f3a9dadf9dd775/packages/next/src/build/templates/app-route.ts#L289-L296
```js
return routeModule.handle(nextReq, context).finally(() => { // <-- handle() returns the response object from the user code
if (!span) return
span.setAttributes({
'http.status_code': res.statusCode, // <---------- this is using some default response object, not what handle() returned
'next.rsc': false,
})
```
The sourcemap file of the polyfill chunk wasn't actually content hashed.
it just used the name of the corresponding JS chunk.
It was still emitted into `_next/static/immutable`. So it wasn't
actually immutable.
Now, it's content hashed (and this also removed the ad-hoc sourcemap
construction from app.rs and instead uses the usual pattern that all
other chunks use to reference their corresponding sourcemap chunks).
We didn't catch this because it only happens with
`nextConfig.productionBrowserSourceMaps: true` which isn't the default.
The test now covers this as well
https://github.com/vercel/next.js/pull/94197 had a bug in the Turbopack
case, where it didn't properly trace all necessary files referenced from
`cacheHandler` and `cacheHandlers`.
If you imported `lodash` in the cache handler, then
- `node_modules/.pnpm/[email protected].1/node_modules/lodash/lodash.js` was
correctly traced
but missing were
- `node_modules/.pnpm/[email protected].1/node_modules/lodash/package.json`
and
- `node_modules/lodash` (the symlink)
The problem was that it wasn't including affecting sources of these
entrypoints, because it was treating those entrypoints as bundled:
```
SingleModuleGraph::new_inner(
entries: Vec<ChunkGroupEntry>,
visited_modules: &FxIndexMap<ResolvedVc<Box<dyn Module>>, GraphNodeIndex>,
include_traced: bool,
include_binding_usage: bool,
entries_are_traced: bool, // <------ problematic
) -> Result<Vc<Self>>
```
should really have been
```
SingleModuleGraph::new_inner(
entries: &GraphEntries, // contains Vec<ChunkGroupEntry> and traced_modules: Vec<Modules
visited_modules: &FxIndexMap<ResolvedVc<Box<dyn Module>>, GraphNodeIndex>,
include_traced: bool,
include_binding_usage: bool,
) -> Result<Vc<Self>> {
```
because the single `entries_are_traced: bool` can be different per
entry.
Recreation of https://github.com/vercel/next.js/pull/90314
---
## Summary
- Fix `--debug-build-paths` pages normalization in Turbopack so
`pages/<name>/index.tsx` maps to `/<name>` (matching JS
`getPageFromPath()` behavior).
- Handle index page edge case: `/index.tsx -> /`.
- Keep regression coverage in
`test/production/debug-build-path/debug-build-paths.test.ts` with a
generic fixture `pages/with-index/index.tsx`.
## Current Behavior Reference
- CI run (before this fix) that failed as expected for this bug:
-
https://github.com/vercel/next.js/actions/runs/22266469801/job/64413677099?pr=90314#step:35:216
## Root Cause
Rust-side debug-build-path normalization removed file extensions but did
not remove `/index`, producing route keys like `/with-index/index` while
pages route keys are `/with-index`. That mismatch filtered out the page
and caused `PageNotFoundError` during page-data collection.
---------
Co-authored-by: devjiwonchoi <[email protected]>
Closes#93994
Unfortunately deploy tests can't pass on external PRs like #93994
currently due to missing secrets
----
The per-request call to ensureInstrumentationRegistered() inside
RouteModule.prepare was missing an await, so when an adapter dispatches
the compiled app-route template's handler without going through
BaseServer.handleRequest (where prepareImpl awaits it via
runInstrumentationHookIfAvailable), a cold-start request could begin
executing the userland route handler before
instrumentation.ts#register() resolved. The other two call sites
(next-server.ts and web/adapter.ts) already await; this aligns the
third.
This only caused a problem with adapters
---------
Co-authored-by: Maurits Misana <[email protected]>
Co-authored-by: Tim Neutkens <[email protected]>
Refactor the module-graph bit of NFT so that we can provide
`Endpoint.traced_files()` which is needed for the bundle analyzer
There should be no logic change whatsoever
- [x] skip traced edges properly in all graph traversals
- [x] iter_nodes and enumerate_nodes include the traced modules
- [x] Don't propagate is_self_async inside of traced references as a perf optimization
- [x] fix performance
- [x] validate that NFT JSON files are identical
- [x] ~~validate/adjust bundle analyzer output~~ will be in followup
- [x] audit `fn chunking_type()` changes
Benchmark:
```
* ced85b3108 - (2 weeks ago) refactor - Niklas Mischkulnig (HEAD -> mischnic/nft-module-graph, origin/mischnic/nft-module-graph)
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 334.96s user 44.57s system 788% cpu 48.152 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 343.39s user 42.61s system 809% cpu 47.659 total
* 5edf48238f - (77 minutes ago) v16.3.0-canary.32 - next-js-bot[bot] (HEAD, tag: v16.3.0-canary.32)
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 333.42s user 43.57s system 712% cpu 52.877 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 332.95s user 43.15s system 791% cpu 47.515 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 337.59s user 41.28s system 771% cpu 49.117 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 335.25s user 45.53s system 718% cpu 52.975 total
```
<details>
<summary>Previous benchmarks</summary>
```
52212418699f362904d64c08e544d4994e8d27fa mischnic/nft-module-graph
pnpm next build 371.41s user 66.39s system 737% cpu 59.353 total
pnpm next build 380.13s user 59.62s system 751% cpu 58.548 total
pnpm next build 374.25s user 60.55s system 761% cpu 57.102 total
8e4cfc5062 canary
pnpm next build 370.77s user 53.89s system 762% cpu 55.725 total
pnpm next build 383.16s user 55.61s system 744% cpu 58.921 total
pnpm next build 382.34s user 53.51s system 757% cpu 57.512 total
pnpm next build 381.15s user 54.50s system 751% cpu 57.943 total
```
```
b0d5411a79 mischnic/nft-module-graph
pnpm next build --experimental-build-mode=compil 368.75s user 62.05s system 749% cpu 57.445 total
pnpm next build --experimental-build-mode=compil 368.95s user 58.42s system 763% cpu 56.004 total
0e3ad2768bd3b036e96f66e4b770a16bb0b38705 mischnic/nft-module-graph
pnpm next build --experimental-build-mode=compil 369.48s user 60.62s system 748% cpu 57.494 total
pnpm next build --experimental-build-mode=compil 374.89s user 52.27s system 730% cpu 58.449 total
pnpm next build --experimental-build-mode=compil 375.02s user 52.89s system 747% cpu 57.274 total
f37073e1d96f6d846cd333b93fccd1dd7bdc253e mischnic/speed-next-dynamic-map
pnpm next build --experimental-build-mode=compil 389.58s user 55.98s system 704% cpu 1:03.21 total
e599b11e2d6b09a92600cfca6d9b338ed1f7537d mischnic/fix-side-effect-edge-removal
pnpm next build --experimental-build-mode=compil 386.60s user 53.34s system 720% cpu 1:01.09 total
f68f70b044 canary
pnpm next build --experimental-build-mode=compil 387.46s user 53.72s system 738% cpu 59.716 total
pnpm next build --experimental-build-mode=compil 390.33s user 53.54s system 734% cpu 1:00.43 total
pnpm next build --experimental-build-mode=compil 385.33s user 56.55s system 722% cpu 1:01.18 total
pnpm next build --experimental-build-mode=compil 386.49s user 56.44s system 726% cpu 1:00.96 total
```
```
b1ed4553e6 origin/mischnic/nft-module-graph
pnpm next build --experimental-build-mode=compile 467.28s user 75.24s system 791% cpu 1:08.56 total
pnpm next build --experimental-build-mode=compile 465.00s user 76.80s system 831% cpu 1:05.20 total
pnpm next build --experimental-build-mode=compile 473.86s user 70.73s system 790% cpu 1:08.90 total
3cb77c844b canary
pnpm next build --experimental-build-mode=compile 367.91s user 58.06s system 726% cpu 58.672 total
pnpm next build --experimental-build-mode=compile 362.97s user 57.68s system 746% cpu 56.379 total
pnpm next build --experimental-build-mode=compile 364.59s user 57.01s system 724% cpu 58.167 total
```
</details>
If the user's `package.json` contains, `type: module`, then the file
generated by Turbopack at `[project]/__next_instrumentation_client.js`
would get treated as ESM. But it always contains CJS, causing
```
Uncaught (in promise) ReferenceError: module is not defined
at module evaluation (__next_instrumentation_client.js:3:1)
```
I set it to `::Unknown` because we the runtime may or may not support
module-sync. So let's just trace both for now
There is one problem though:
https://nodejs.org/docs/latest-v26.x/api/packages.html#conditional-exports
> "module-sync" - matches no matter the package is loaded via import,
import() or require(). The format is expected to be ES modules that does
not contain top-level await in its module graph - if it does,
ERR_REQUIRE_ASYNC_MODULE will be thrown when the module is require()-ed.
So we have multiple options:
1. We definitely want to respect module-sync for tracing. We don't
really have to throw ERR_REQUIRE_ASYNC_MODULE here, Node.js will do it
at runtime anyway.
2. ~~What about bundling? Either~~
- ~~Respect module-sync always, but don't throw
ERR_REQUIRE_ASYNC_MODULE.~~
- ~~Respect module-sync always, and do throw a build error the module
requires TLA. This would require a separate validation pass though.~~
- I'm not enabling it for bundling for now
Adapters implementing `modifyConfig` may need to know the absolute
project directory to perform path resolution or apply directory-specific
configuration logic. Without this value, adapters had no reliable way to
determine where the application lives on disk.
onBuildComplete already received the directory as a parameter.
- [x] fix tests
- [ ] add experimental flag and only enable in adapter? or is this cheap
enough to just always do?
- [x] disable for webpack
Closes PACK-6541
For https://github.com/nextjs/adapter-vercel/pull/24
Newer version of https://github.com/vercel/next.js/pull/89534
- Add a hashes mapping to the NFT file
- Forward that information to the adapter via `assetsHashes` for
functions
Basically zero-cost:
```
commit ad728b15a6431a6372eea3d3d766b328569811b4 (HEAD -> mischnic/server-paths-manifest-2, origin/mischnic/server-paths-manifest-2)
pnpm next build 351.22s user, 51.55s system, 811% cpu, 49.654 total
pnpm next build 354.52s user, 53.39s system, 837% cpu, 48.706 total
pnpm next build 344.02s user, 63.62s system, 749% cpu, 54.368 total
pnpm next build 353.74s user, 54.25s system, 833% cpu, 48.970 total
commit 04294cb47a (origin/canary, origin/HEAD)
pnpm next build 344.24s user, 53.88s system, 798% cpu, 49.845 total
pnpm next build 340.89s user, 52.40s system, 784% cpu, 50.138 total
pnpm next build 347.26s user, 51.91s system, 802% cpu, 49.741 total
pnpm next build 347.04s user, 52.65s system, 803% cpu, 49.764 total
```
1. https://github.com/vercel/next.js/issues/93516 was first opened.
Everything worked. It introduced one more `< MAX_INLINE_LEN` comparison
2. https://github.com/vercel/next.js/issues/93524 fixed an off-by-one
error (which was fine all long as all of them were consistently off by
one)
3. Then https://github.com/vercel/next.js/issues/93516 merged without
rebasing and on canary, the one added callsite was now inconsistent with
the rest. So CI failed on canary
This caused a lot of test failures:
```
➜ next.js git:(canary) UPDATE=1 cargo nextest run -p turbopack-tests -E 'test(test_tests__execution__webpack__scope_hoisting__esModule__input__index_js)' --no-capture
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.55s
────────────
Nextest run ID a86cddd0-85b8-4f6c-b550-0e5870a9daf1 with nextest profile: default
Starting 1 test across 3 binaries (305 tests skipped)
START [ ] (1/1) turbopack-tests::execution test_tests__execution__webpack__scope_hoisting__esModule__input__index_js
running 1 test
Input: next.js/turbopack/crates/turbopack-tests/tests/execution/webpack/scope-hoisting/esModule/input/index.js
updated contents of turbopack/crates/turbopack-tests/tests/execution/webpack/scope-hoisting/esModule/issues/Code generation for chunk item errored-803648.txt
thread 'test_tests__execution__webpack__scope_hoisting__esModule__input__index_js' (46528180) panicked at turbopack/crates/turbopack-tests/tests/execution.rs:105:9:
Failed with error(s) in the following test(s):
"should have the __esModule flag":
Error: An error occurred while generating the chunk item [project]/turbopack/crates/turbopack-tests/tests/execution/webpack/scope-hoisting/esModule/input/module.js [test] (ecmascript)
Caused by:
- Processing [project]/turbopack/crates/turbopack-tests/tests/execution/webpack/scope-hoisting/esModule/input/module.js [test] (ecmascript)
- Expected to find a local export for default with ctxt #4 in {"default": ("__TURBOPACK__default__export__", #0)}
Debug info:
- An error occurred while generating the chunk item [project]/turbopack/crates/turbopack-tests/tests/execution/webpack/scope-hoisting/esModule/input/module.js [test] (ecmascript)
- Execution of <MergedEcmascriptModule as EcmascriptChunkPlaceable>::chunk_item_content failed
- Execution of *EcmascriptChunkItemContent::new failed
- Execution of EcmascriptModuleContent::new_merged failed
- Processing [project]/turbopack/crates/turbopack-tests/tests/execution/webpack/scope-hoisting/esModule/input/module.js [test] (ecmascript)
- Expected to find a local export for default with ctxt #4 in {"default": ("__TURBOPACK__default__export__", #0)}
```
Brought to you by
```
destructor of `std::option::Option<turbo_rcstr::RcStr>` cannot be evaluated at compile-time
```
and
```
cannot perform conditionally-const deref coercion on `std::mem::ManuallyDrop<std::option::Option<RcStr>>` in constants
```
It never made sense to have module references that point to an output
asset, and the `ChunkingType` value on those made even less sense. We
had already migrated almost everything off anyway
- SingleModuleReference is dead code, never actually called
- SingleOutputAssetReference was created, but never actually did anything because of the ChunkingType being None
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Signed commits
- This repository requires verified commit signatures on protected
branches.
- If this pull request is blocked for unsigned commits, re-sign the
commits and force-push the branch.
- A `Signed-off-by` line in the commit message is not enough.
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
Currently doesn't have a measureable performance impact.
Previously we assigned module ids for all nodes in the graph, even the subgraphs we detect as unused. They weren't chunked already, but the codegen that references those wasn't gracefully handling `.chunk_item_id(m)` failing (where `m` is a unused skipped module)
So `.iter_nodes()` should basically be deprecated. It doesn't respect `removed_unused_imports` and the side-effect-free inference.
And this would get much much worse once NFT is on the module graph, because then there are way more modules that should be skipped via the same mechanism
This manifested as the following error after switching from `.iter_nodes` to `.traverse_edges_unordered` in global_module_ids.rs
```
Debug info:
- An error occurred while generating the chunk item [project]/node_modules/.pnpm/next@file+..+next.js+packages+next_@[email protected].0_@[email protected]_@playwri_9a8ea08672cbf59c2720abbb0c8879be/node_modules/next/dist/esm/server/stream-utils/node-web-streams-helper.js [app-rsc] (ecmascript)
- Execution of <MergedEcmascriptModule as EcmascriptChunkPlaceable>::chunk_item_content failed
- Execution of *EcmascriptChunkItemContent::new failed
- Execution of EcmascriptModuleContent::new_merged failed
- ModuleId not found for ident: [project]/node_modules/.pnpm/next@file+..+next.js+packages+next_@[email protected].0_@[email protected]_@playwri_9a8ea08672cbf59c2720abbb0c8879be/node_modules/next/dist/esm/shared/lib/hash.js [app-rsc] (ecmascript)
```
Currently doesn't have a measureable performance impact.
Attempt the cheap downcast first and only do the ident reading and
comparison in the uncommon case
We don't actually need the full analysis to compute exports. This can
break some task cycles, and might theoretically improve task latency.
The CPU time appears to be marginally higher (but not statistically
significant), but no impact on overall build time:
```
* c4fdcc2651 - (14 hours ago) compute exports before final_read_hint() - Niklas Mischkulnig (origin/mischnic/get-exports-without-analyze, mischnic/get-exports-without-analyze)
pnpm next build --experimental-build-mode=compile 378.10s user 58.28s system 760% cpu 57.411 total
pnpm next build --experimental-build-mode=compile 383.64s user 60.32s system 738% cpu 1:00.10 total
pnpm next build --experimental-build-mode=compile 378.70s user 55.65s system 718% cpu 1:00.41 total
* 8ddc1cdbdd - (38 minutes ago) Use OIDC for CodSpeed (#93059) - Niklas Mischkulnig (origin/canary, origin/HEAD, canary)
pnpm next build --experimental-build-mode=compile 376.95s user 58.30s system 755% cpu 57.597 total
pnpm next build --experimental-build-mode=compile 375.85s user 61.75s system 738% cpu 59.230 total
pnpm next build --experimental-build-mode=compile 377.75s user 63.00s system 729% cpu 1:00.39 total
```
`resolve_origin.get_inner_asset` showed up in Luke's statistics at a
very high place.
But in reality, there are only 1-3 modules per page that have any inner
assets (the templates, and the edge wrapper modules).
`resolve_origin.get_inner_asset` is in the hottest hot path (resolving
references), so let's simply move this logic into the
EcmascriptModuleAsset itself.
Behavioral differences to before:
- only works with static ESM `import`s, dynamic `import()`, `require`,
`require.resolve`. But these are the only places that currently use it
anyway.
```
0d9738112f mischnic/remove-get-inner-asset
pnpm next build --experimental-build-mode=compile 353.40s user 52.96s system 748% cpu 54.265 total
pnpm next build --experimental-build-mode=compile 349.42s user 53.84s system 744% cpu 54.198 total
pnpm next build --experimental-build-mode=compile 352.42s user 54.46s system 741% cpu 54.874 total
3cb77c844b canary
pnpm next build --experimental-build-mode=compile 367.91s user 58.06s system 726% cpu 58.672 total
pnpm next build --experimental-build-mode=compile 362.97s user 57.68s system 746% cpu 56.379 total
pnpm next build --experimental-build-mode=compile 364.59s user 57.01s system 724% cpu 58.167 total
```
I'm moving all of the export-related logic into `EvalContext` (and thus
`ImportMap`) so that `VarGraph` is only needed for computing the
references, and not the exports.
So that
```ts
export const runtime = "node" as const
export const runtime = "node" as string
export const runtime = "node" satisfies string // was already working
```
works
I'm moving all of the export-related logic into `EvalContext` (and thus `ImportMap`) so that `VarGraph` is only needed for computing the references, and not the exports.
The change in the snapshots is
```diff
-*anonymous function 170* (const after eval) = (...) => [file]
+*anonymous function 170* = (...) => [file]
```
which is fine, since computing the "is reassigned" data for something that isn't actually a variable was non-sensical anyway.
- defer computing the `EsmAssetReference` issue source from the `Span`. means that we have to pass less arguments around as well
- make `mangle("default export")` a "constant" and use that everywhere instead
Some snapshots changed, because the test runner had `source: None`, so now there are some duplicate module references in there because the new always-set `span` field forces it to be a new entry in the `data.references` hashmap.
There is actually no reason to compute `full_star_imports` before the `visit_with(&mut analyzer)`: it's only used later on by references/mod.rs which calls `should_import_all`.
So we can just do it in the same traversal
### What?
Closes https://github.com/vercel/next.js/pull/92650
Closes https://github.com/vercel/next.js/issues/92547
When Turbopack runs SWC transform plugins, it passes a `TransformPluginMetadataContext` that includes the current `NODE_ENV`. Previously this value was hardcoded to `"development"` regardless of the actual build mode, causing SWC plugins to misbehave during production builds.
### Why?
`SwcPluginMetadataContext` is used by SWC plugins (e.g. `babel-plugin-styled-components`, `@swc/plugin-emotion`) to conditionally produce development vs. production output — for instance, injecting display names and data attributes only in development. With `NODE_ENV` always set to `"development"`, plugins could never produce their optimised production output, resulting in larger bundles and missing minification in `next build`.
Fixes https://github.com/vercel/next.js/issues/92547
### How?
`NODE_ENV` is now derived from the `process.env.NODE_ENV` compile-time define that is already part of `CompileTimeInfo` (the same source of truth used for dead-code elimination). The resolution happens in `EcmascriptModuleAsset::parse()` via a new shared helper `node_env_from_compile_time_info()` in `parse.rs`, and the value is stored on `TransformContext` so every `CustomTransformer` implementation can read it from `ctx.node_env` without needing access to the broader compilation context.
Key design decisions:
- **`TransformContext`** is the right place: it is the per-file context passed to every `CustomTransformer::transform()` call, so storing `node_env` there follows the existing pattern and avoids coupling the plugin struct to the build mode.
- **Webpack analysis path**: `compile_time_info` is now threaded through `webpack_runtime()`, `module_references()`, and the webpack reference structs (`WebpackModuleAsset`, `WebpackChunkAssetReference`, `WebpackEntryAssetReference`, `WebpackRuntimeAssetReference`) so that webpack-bundled files with SWC plugin transforms also receive the correct `NODE_ENV`.
- **`segment_config.rs`**: passes a placeholder but includes a comment explaining it is irrelevant since `EcmascriptInputTransforms::empty()` means no transforms run.
<!-- NEXT_JS_LLM_PR -->
To see if we have any tests at all for this...
Was added here: https://github.com/vercel/next.js/commit/b20f02830c03053bee650049830db065878cf6a1 `add special case for tracing webpack bundles` by @sokra
We can add this back again with a better implementation if we end up needing this anyway
Looks like this was used to trace webpack chunks, particularly back from the time when we used to trace the output chunks.
Just adding some test coverage
- Turbopack: module are only evaluated when the given module is actually
rendered
- Webpack: all client component modules are evaluated when at least one
client reference renders