Commit Graph

291 Commits

Author SHA1 Message Date
Benjamin Woodruff ‮ 7b58e5880c Turbopack: Add support for specifying additional roots (#98003)
Full motivation and plan here:
https://app.notion.com/p/vercel/Turbopack-pnpm-Global-Virtual-Store-383e06b059c480579403ddfd71cc2d40?source=copy_link

The goal is to allow `DiskFileSystem` to traverse outside of it's own
root to other configured `DiskFileSystem`s when following symlinks. We
may allow traversal in other situations in the future, but this is
limited to symlink resolution for now.

## Global Virtual Store

The motivation for this is to enable [pnpm's Global Virtual Store
feature](https://pnpm.io/global-virtual-store) (and there are other
package managers doing this, including nub and bun).

We'd expose the ability to manually configure this in `next.config.js`,
but we should also auto-configure ourselves for popular package managers
(or at least make a best effort to do so, the `PNPM_HOME` semantics can
be complicated). The `ignoreIfMissing` option is provided for this
situation: We can configure a bunch of roots automatically, and they
only actually get set up if they exist, the check for directory
existence is cheap.

## NFT changes

This requires a couple extensions to the `*.nft.json` file format:
https://github.com/vercel/next.js/pull/98469

## Related Issues

- #93556
- https://github.com/pnpm/pnpm/issues/14972
2026-09-18 17:08:40 -07:00
Will Binns-Smith d5276f04a1 Make TurbopackResult payloads disjoint (#98575)
### What?

Refactors the JavaScript-facing `TurbopackResult<T>` into a stable
wrapper whose payload lives under `value` and whose issues remain
top-level. Native API consumers, entrypoint conversion,
development-server paths, HMR handling, and direct API tests now follow
the disjoint shape.

Two event subscriptions that had inaccurate wrapper declarations now
expose their existing plain runtime payloads explicitly: update-info
events remain `UpdateMessage`, and compilation events remain
`CompilationEvent`. Nullable native entrypoint payloads are also
declared accurately and normalized at the JavaScript API boundary.

### Why?

The previous intersection-based representation merged payload fields
with result metadata. That allowed fields such as `issues` to overwrite
one another and caused non-object payloads to be discarded, making the
result shape depend on `T`. A dedicated payload property avoids those
collisions and preserves every payload type, including `null`.

Keeping plain event streams distinct from result wrappers also ensures
`TurbopackResult<T>` consistently means the native API actually provides
wrapper metadata.

### How?

The N-API serializer now always creates a fresh wrapper rather than
mutating an object payload. The shared TypeScript type models that
wrapper directly and requires an explicit payload type. Conversion
layers replace only the nested payload while explicitly preserving
wrapper issues. Call sites continue to process wrapper issues while
reading domain data through `value`.

The update-info and compilation-event declarations were aligned with
their native callback types instead of introducing new runtime wrappers
for streams that do not collect issues. Rust `Option<NapiEntrypoints>`
payloads are declared as nullable, then normalized to the existing
empty-entrypoints representation after a null-safe route check.

### Verification

- `pnpm build-all`
- `pnpm --filter=next types`
- `pnpm swc-build-native`
- `cargo check -p next-napi-bindings`
- `cargo fmt --all -- --check`
- ESLint and Prettier on changed files
- `pnpm test-dev-experimental-turbo
test/development/app-aspath/app-aspath.test.ts`
- `pnpm test-dev-turbo test/development/basic/next-rs-api.test.ts` — 26
passed, 1 skipped, 15 snapshots; Jest reported lingering open handles
after the green summary
- `pnpm test-dev-turbo
test/development/app-dir/concurrent-install/concurrent-install.test.ts`
- `pnpm test-dev-experimental-turbo
test/development/app-dir/concurrent-install/concurrent-install.test.ts`

<!-- NEXT_JS_LLM -->

<!-- fleet 74688340-f99a-462e-8f75-88d12c88000a -->

---------

Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com>
Co-authored-by: Will Binns-Smith <755844+wbinnssmith@users.noreply.github.com>
2026-09-11 16:25:09 -07:00
Sebastian "Sebbie" Silbermann 6ba71046b0 [test] Move the harness off node-fetch (#98195)
Node.js ships with a built-in `fetch` now so `node-fetch` is no longer
necessary. Mostly motivated by tracing Node.js deprecation warnings
which originated from `node-fetch` by calling the deprecated
`url.parse`.

Call sites keep working through a compatibility type on `fetchViaHTTP`
that translates node-fetch-only options: Instead of `agent` we pass to
`http(s)` directly, `timeout` becomes `AbortSignal.timeout`, and Node.js
readable streams are accepted as bodies with `duplex: 'half'` set
automatically.

The `abort-controller` polyfill is dropped since its signal type
predates the current AbortSignal and undici would not honor it.
`node-fetch` stays installed because `scripts/generate-release-log.mjs`,
`scripts/reset-project.mjs`, and `scripts/update-google-fonts.js` still
import it (follow-up material). Fixture apps will be migrated
separately.
2026-09-10 13:50:35 +02:00
Jiwon Choi d7aa66c345 Remove generated error codes (#97687)
### Why?

Should come up with better solution that does not block PRs with git
conflict

x-ref:
https://vercel.slack.com/archives/C02CDC2ALJH/p1785263902728189?thread_ts=1785263687.502649&cid=C02CDC2ALJH

### How?

- Delete `errors.json`, the error-code SWC plugin, generated WASM, merge
driver, and validation/build tooling.
- Stop attaching error codes to server-rendering digests, redboxes, and
telemetry; native `Error.code` and `Error.name` remain available where
applicable.
- Remove the development-overlay error feedback UI, middleware, and
telemetry event that depended on stable codes.
- Update fixtures, snapshots, and guidance for code-free errors and
numeric-only digests.

<!-- NEXT_JS_LLM -->
2026-08-21 22:45:12 +02:00
zoomdong d820350579 feat(turbopack): isolate HMR listeners across microfrontends (#95997)
## Summary

When two Next.js microfrontend child applications run in development
mode at the same time, their HMR clients conflict because they share the
same global chunk-update listener registry.

Since turbopack added support for the chunkloadingglobal configuration,
I think this configuration can also consume HMR's global object
simultaneously: PR: https://github.com/vercel/next.js/pull/88790 and
https://github.com/vercel/next.js/pull/93488

This change scopes the listener registry to each runtime chunk-loading
global so the applications can receive HMR updates independently.

## Test

Update snapshot test case
2026-08-21 11:19:16 +02:00
Will Binns-Smith e2fb664ceb Remove HmrTarget (#97253)
With #94948 we intended to move the client over to the firehose feed of
HMR events with the intent of unifying the code paths for maintenance.
However, now that Server HMR is moving to a pull-based model (which
client HMR will not be able to implement), let's keep the split.

There's no need to encode the HmrTarget into each surface, and we can
just use the function name to indicate which mode of HMR it's for.
2026-08-19 17:22:47 -07:00
Tobias Koppers da8fc4fea3 fix(turbopack): point at the glob that matched a file with no module type (#96561)
A build error for a glob-matched file with no module type named only the
file,
with no route, call site or import trace — the file never becomes a
module, so
it has no place in the module graph. `import.meta.glob` now also reports
an
error at the call site with the pattern and matched key. Also fixed the
stale
`Read more` link (308s to a page whose anchor changed).

<!-- NEXT_JS_LLM -->

Co-authored-by: vercel-fleet[bot] <308483924+vercel-fleet[bot]@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
2026-08-10 08:58:33 +02:00
Tim Neutkens cbf0cef687 Enable TypeScript CLI by default (#96497)
## Summary

Enable the project-local TypeScript CLI checker by default during `next
build`, while preserving `experimental.useTypeScriptCli: false` as an
opt-out to the TypeScript compiler API. Update the TypeScript 7
guidance, diagnostics, tests, and documentation to match the new
default.

## Verification

- `pnpm exec jest --runTestsByPath test/unit/isolated/config.test.ts`
- Pre-commit lint-staged checks passed (Prettier and ESLint)
- Not run: `pnpm test-start-turbo
test/production/app-dir/typescript-cli/typescript-cli.test.ts` (isolated
fixture dependency installation was blocked by unavailable npm registry
access)
- Not run: `pnpm --filter=next types` (repository has pre-existing
unrelated TypeScript errors)

<!-- NEXT_JS_LLM -->
2026-08-03 18:10:51 +02:00
Benjamin Woodruff 337a40c672 [ci] Pin typescript version in tests (#95619)
Typescript 7 came out, which is breaking a lot of our e2e tests.
2026-07-08 14:12:48 -07:00
Sam Poder bb9af37519 [turbopack] Rename rscEndpoint to rscHmrEndpoint (#95538)
I'm introducing a new endpoint that doesn't compile SSR when doing a
page navigation, I'd like to call it a `rscEndpoint` but currently this
name is taken. `rscEndpoint` appears to be used for detecting changes
for HMR so I've renamed it to `rscHmrEndpoint` so I can use that name
for the new `rscEndpoint`.
2026-07-07 18:19:40 -07:00
Benjamin Woodruff 7cb54ace75 [ci] Update playwright to 1.61.0 (#94871)
[Playwright v1.61.0 adds support for
ubuntu-26.04](https://github.com/microsoft/playwright/releases/tag/v1.61.0).
When Lindsey created our arm64 runners (see
https://github.com/vercel/next.js/pull/94870), [he picked the
ubuntu-26.04
image](https://vercel.slack.com/archives/C01LN7C5QR5/p1781608258610389?thread_ts=1781118174.353839&cid=C01LN7C5QR5)
(which is technically still [in
preview](https://github.com/actions/runner-images#available-images), but
IMO that's fine).
2026-06-18 21:39:11 +00:00
Niklas Mischkulnig 9b8a7a1055 Turbopack: improve issue printing colors (#94858)
1. Align the code highlight marker color with the issue severity
2. Make the issue title colored
3. Prefix issues with `Warning` or `Error`


<img width="1383" height="862" alt="Bildschirmfoto 2026-06-16 um 18 59
03"
src="https://github.com/user-attachments/assets/f98c606d-4ea8-40c2-836d-e395f1df904c"
/>


<img width="1039" height="450" alt="Bildschirmfoto 2026-06-16 um 19 03
39"
src="https://github.com/user-attachments/assets/2747f914-0587-4178-a87d-344f24715c96"
/>



<details>
<summary>Old</summary>

<img width="1267" height="745" alt="Bildschirmfoto 2026-06-16 um 17 04
35"
src="https://github.com/user-attachments/assets/837739ff-82f7-4ea2-8767-ca7d866a8570"
/>

</details>
2026-06-16 21:29:37 +02:00
Hendrik Liebau 96d7526ce3 Add a cold cache dev indicator (#94611)
When Cache Components is enabled, a `next dev` load that streams while
filling an empty cache is not representative of production: cached
content streams in as it is computed rather than being served instantly,
and React's DevTools cannot accurately show what would normally suspend.
This surfaces that state in the dev indicator. While a client navigation
is pending the rendering pill is colored and labeled by the cache state
(teal "Rendering" normally, orange "Rendering (cold cache)" when the
render hit an empty cache, and orange "Rendering (cache disabled)" when
caches were bypassed), and once the load settles a cold or bypassed load
leaves a persistent, dismissible orange badge ("Cold cache" or "Cache
disabled") with an info panel that explains why the load was not
production-like and suggests reloading once the caches are warm.



https://github.com/user-attachments/assets/9be2c35a-3a36-47d7-8803-6e284c332a4b


The indicator's displayed state is now owned by a single state machine,
`useIndicatorDisplay`, rather than being composed from a debounce
(`useDebouncedValue`) and a delayed render (`useDelayedRender`) whose
delays compounded and were hard to reason about. It models the indicator
as an explicit set of phases (idle, entering, pill, exiting, badge)
driven by the raw compiling, rendering, and cache-status signals, and it
hands the rendering pill off to the persistent badge in a single commit
so the indicator never collapses to the bare logo between them. It also
unifies the pre-existing "Cache disabled" badge with the new cold-cache
state so both flow through one path (a navigation shows "Rendering
(cache disabled)" and then settles into the badge). The Cold cache badge
tracks the most recent load, so a later navigation that settles warm
clears it.

The rework also collapses the timing into a single 200ms window for both
showing and hiding, matching the transition used elsewhere in the dev
overlay, and relabeling between active states (for example "Compiling"
to "Rendering", or the flip to the cold-cache color) is now immediate.
This is intentional: the previous debounce held a label on screen past
the moment its underlying state ended, so "Compiling" could linger after
the compile had finished and make the bundler look slower than it
actually was. The one genuine flicker the old debounce guarded against,
the pill blinking out to the bare logo when the status briefly drops
between rapid compile bursts, is still prevented by the new exit linger.

Two cases are knowingly not handled yet: a short-lived `'use cache'`
entry and a `'use cache: private'` entry both report a miss on every
load, so they show the badge even on a warm reload. These are
limitations of the current dev cache behavior rather than of the
indicator, and the tests cover them with `TODO`s that point at the
follow-up changes that will fix them.
2026-06-10 11:45:07 +02:00
Luke Sandberg f32234cc1a Turbopack: Add an experimental option for eviction (#94439)
`experimental.turbopackMemoryEviction = "full" | false`

controls the new feature, currently it is disabled.
2026-06-07 16:38:35 +00:00
Will Binns-Smith 8216e23a07 Turbopack: reduce hmr chunk list subscriptions (#94062)
Previously, we created chunk list register chunks for every reachable
chunk in the chunk graph on a page. Now, we only create one that
subscribes to all recursively reachable assets.

This has to pass around an explicit list of client references chunks as
those cannot be discovered via the chunk graph alone.

This results in a significant performance improvement when loading pages
with the dev server, improving performance of a 60s cold build in a
large app by about 10s.
2026-05-29 12:12:09 -07:00
Tim Neutkens e860cec656 test: migrate webdriver callers to next.browser (#93941)
### What?

Migrate remaining direct `next-webdriver` test callers that have a
`NextInstance` to `next.browser()`, and expose the shared `Playwright`
browser type from `e2e-utils`.

### Why?

`NextInstance.browser` should be the supported browser-opening interface
for test fixtures, with `next-webdriver` kept as the private
implementation detail.

### How?

Updated affected development, e2e, and production tests to call
`next.browser()` directly, passing `baseUrl` where tests intentionally
target a manually spawned or proxied server. Shared helpers now receive
browser callbacks from the test context, and browser types import
`Playwright` from `e2e-utils` instead of deriving from `next.browser` or
importing from private paths.

<!-- NEXT_JS_LLM_PR -->
2026-05-22 14:01:58 +02:00
Tim Neutkens 7da98e1318 Convert more tests from createNext -> nextTestSetup (#93799)
## What?

Converts more tests that use `createNext` to `nextTestSetup`

Follow-up to #93767

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 09:51:36 +02:00
Tim Neutkens 4588a73542 Convert tests using createNext -> nextTestSetup (#93767)
## What?

Converts existing `createNext()` usage into `nextTestSetup()`. 

`createNext()` was the setup step we had before `nextTestSetup()` was
added.

This PR focused on the simple conversion cases. There will be a
follow-up to complete the last few.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 13:16:31 +02:00
Luke Sandberg e8f8f498e8 [turbopack] fix feature usage telemetry (#93100)
## Report Turbopack feature-usage telemetry

Turbopack never reported `NEXT_BUILD_FEATURE_USAGE` telemetry for production builds. This PR wires it up and fixes a correctness bug in how the counts were computed, then cleans up the API surface that carried them across the napi boundary.

### Changes

- **JS**: `turbopackBuild()` now records `EVENT_BUILD_FEATURE_USAGE` events after `writeAllEntrypointsToDisk` via a new `eventBuildFeatureUsageFromTurbopackDiagnostics` helper. Dev is out of scope — webpack's `TelemetryPlugin` is `!dev && isClient` too.
- **Rust**: aligned feature names with the JS `EventBuildFeatureUsage['featureName']` union — SWC triple is now `swc/target/<triple>`; dropped `persistentCaching` (redundant with `turbopackFileSystemCache`) and `turbotrace: false` (hardcoded).

### Correctness fix: count unique importers, not resolves

Previously feature-usage counts for module imports (`next/image`, `next/font/google`, …) were computed from a `BeforeResolvePlugin` that emitted one event per resolve. Turbopack caches resolves, so the emission fired at most **once per unique request** — the count was effectively `1` for every feature that was imported anywhere. Webpack's equivalent counts unique importing modules via `moduleGraph.getIncomingConnections(module).size`.

This PR replaces the resolve-plugin emission with a single whole-app module-graph traversal on `Project`. For each tracked feature, we accumulate the set of unique parent modules of each matching node (mirroring webpack's "unique origin modules" semantics). Fonts are matched against their synthesized `/target.css?…` virtual modules produced by the SWC font-loader transform — matching webpack's `FEATURE_MODULE_REGEXP_MAP` approach. Paths are matched via `phf_map!` tables in `next_telemetry.rs`.

### Incidental simplifications

While in here, the `Diagnostic` collectibles subsystem got right-sized and then removed entirely, since feature usage was its only consumer:

- `Project::project_feature_usage()` returns a structured `Vc<ProjectFeatureUsageSummary>` instead of emitting diagnostics. Surfaced to JS as a dedicated `project.featureUsage(): Promise<BuildFeatureUsage[]>` napi method, called once at build's end.
- `TurbopackResult<T>` loses its `diagnostics: BuildFeatureUsage[]` field — it's now just `{ result, issues }`. Every napi result type and ~10 construction sites are correspondingly simpler.
- Deleted `turbopack_core::diagnostics` entirely (`Diagnostic` trait, `DiagnosticExt`, `DiagnosticContextExt`, `CapturedDiagnostics`, `PlainBuildFeatureUsage`). Deleted `FeatureUsageTelemetry`, `ModuleFeatureReportResolvePlugin`, `get_diagnostics()` aggregation, the `feature_usage`/`diagnostics` fields on `AllWrittenEntrypointsWithIssues`/`OperationResult`/`EntrypointsWithIssues`/`WrittenEndpointWithIssues`/`HmrUpdateWithIssues`/`HmrChunkNamesWithIssues`/`EndpointIssuesAndDiags`/`WriteAnalyzeResult`, and the defensive `drop_collectibles::<Box<dyn Diagnostic>>()` scrub in `entrypoints_without_collectibles_operation`.

Feature-usage telemetry now flows as a plain return value end-to-end: `Project::project_feature_usage()` → napi `projectFeatureUsage()` → JS `project.featureUsage()` → `telemetry.record()`. No collectibles, no peeking, no emission-as-side-effect.

### Tests

Un-skipped four previously webpack-only integration tests in `test/integration/telemetry/test/config.test.ts`: `image/script/dynamic`, `next/legacy/image`, `transpilePackages`, and middleware options. All pass under Turbopack. The remaining three skipped tests (`swc` flags, `@vercel/og`, `useCache`) cover features Turbopack doesn't emit yet — left skipped with TODOs.

Added unit test for the helper at `packages/next/src/telemetry/events/build.test.ts`. Updated the Turbopack `next-rs-api` snapshot to reflect the new diagnostic shape.

<!-- NEXT_JS_LLM_PR -->
2026-05-10 17:50:30 -07:00
Niklas Mischkulnig 26cfeb8531 Allow overriding outputHashSalt in modifyConfig (#92856) 2026-04-16 12:43:26 +02:00
Tobias Koppers 69264a763f test: reduce writeToDisk memory test iterations to fix CI timeout (#92586)
### What?

Reduces `RUNS` from 10,000 to 1,000 in the `next.rs api writeToDisk
multiple times` test in `test/development/basic/next-rs-api.test.ts`.

### Why?

The test was frequently timing out on CI. It spawns a child `node
--expose-gc` process that calls `writeToDisk()` in a loop (`RUNS` times
per batch) for each discovered route (~11 routes), with up to 11
measurement batches per route. At 10,000 runs per batch that is up to
~1.1 million `writeToDisk()` calls total — all under the global
60-second Jest timeout.

Each call, even in the turbo-tasks memoized steady state, has
non-trivial overhead: an NAPI crossing, a task-cache lookup, a
`read_strongly_consistent()` wait, and an O(N effects) iteration over
output assets (each requiring a mutex acquisition). On slow CI hardware
this easily exceeds 60 seconds.

### How?

Reduce `RUNS` to 1,000. This gives a 10× speedup without compromising
the test's ability to detect memory leaks: a leak of even a single OS
page (4 KB) per 1,000 calls is still detectable via the RSS delta check.
The warmup + measurement loop structure is unchanged.

<!-- NEXT_JS_LLM_PR -->

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-04-10 08:52:46 +00:00
Sebastian "Sebbie" Silbermann c8305764f6 [test] Stop using deprecated target: "es5" TypeScript compiler option (#92458) 2026-04-09 14:19:57 +02:00
Chris Tate daca04d09b Allow multi-level .localhost subdomains in dev origin check (#92262)
## Summary

The built-in dev origin allowlist uses `*.localhost`, but `*` only
matches a single subdomain level. Multi-level `.localhost` subdomains
like `sub.app.localhost` are blocked even though all `.localhost`
domains resolve to loopback per RFC 6761.

This changes `*.localhost` to `**.localhost` so any depth of
`.localhost` subdomain is auto-allowed. The `**` glob is already
supported by `matchWildcardDomain` in `csrf-protection.ts`.

- `**.localhost` matches `app.localhost` (single level, same as before)
- `**.localhost` matches `sub.app.localhost` (multi-level, previously
blocked)
- Bare `localhost` is already separately in the allowlist, unaffected
2026-04-02 15:37:13 +00:00
Tobias Koppers 3e0158846e feat: add NEXT_HASH_SALT env var for content-hash filename salting (#91871)
### What?

Adds a `NEXT_HASH_SALT` environment variable **and** a
`experimental.outputHashSalt` config option that mix a user-supplied
string into every content-addressed hash used to generate chunk
filenames and static asset filenames. This works for both Webpack and
Turbopack.

When both are set, the values are concatenated (`outputHashSalt +
NEXT_HASH_SALT`), so a per-project salt can be baked into
`next.config.js` while a per-deployment salt is injected at build time
via the environment variable.

### Why?

Content-addressed filenames (e.g. `chunk.abc123.js`) are derived from
file content, so they only change when the content changes. There are
deployment scenarios where you need to force all filenames to rotate —
for example after a CDN misconfiguration has poisoned caches for a
particular hash space — without actually changing source code. A stable,
opt-in salt lets operators do this without touching application code.

Some customers prefer the config-file approach
(`turbopack.outputHashSalt`) over environment variables, so both are
supported.

### How?

**Webpack** already has `output.hashSalt` in its config. We simply
forward `NEXT_HASH_SALT` to that option.

**Turbopack** required threading the value through several layers:

1. The effective hash salt is computed once in
`assignDefaultsAndValidate` as `config.turbopackHashSalt =
(turbopack.outputHashSalt ?? '') + (NEXT_HASH_SALT ?? '')` and stored on
`NextConfigComplete`. Both `turbopackBuild` (production) and
`createHotReloaderTurbopack` (dev) read from this single field.
2. `ProjectOptions.hash_salt` receives the pre-computed salt.
3. `Project` stores the salt and passes it into the three chunking
context option structs (`ClientChunkingContextOptions`,
`ServerChunkingContextOptions`, `EdgeChunkingContextOptions`).
4. Both `BrowserChunkingContext` and `NodeJsChunkingContext` gain a
`hash_salt: RcStr` field.
5. A new `deterministic_hash_with_salt(salt, input, algorithm)` function
in `turbo-tasks-hash` writes the salt bytes first, then the content
bytes, into a single hasher — one pass, no hash-of-hash composition.
6. A matching `content_hash_with_salt` method is added to `FileContent`
and `AssetContent`.
7. `ChunkingContext::asset_path` is changed to accept `Vc<AssetContent>`
(instead of a pre-computed `Vc<RcStr>`) so the chunking context can
choose the correct hash path itself. `StaticOutputAsset::path`
simplifies accordingly.

Without `NEXT_HASH_SALT` and without `turbopack.outputHashSalt` set,
behaviour is identical to before — no hash change, no performance
impact.

**e2e test** (`test/production/app-dir/hash-salt/`) verifies:
- Two builds with the same salt produce identical chunk and static asset
filenames.
- A build with a different salt produces different filenames.
- `turbopack.outputHashSalt` (config) changes filenames vs no salt.
- Combined config + env salt differs from either alone.
- Runs for both Turbopack and Webpack.

---------

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Luke Sandberg <lukesandberg@users.noreply.github.com>
2026-04-01 22:03:50 +02:00
Sebastian "Sebbie" Silbermann 77c84b4dac [test] Deflake allowed-dev-origins (#92211) 2026-04-01 18:11:26 +00:00
Tim Neutkens 89871864ed Rename /_next/webpack-hmr to /_next/hmr (#91415)
## What

Rename the HMR WebSocket path from `/_next/webpack-hmr` to `/_next/hmr`.

## Why

The `webpack-hmr` name is a leftover from when webpack was the only
bundler. Now that Turbopack is the default bundler for both `next dev`
and `next build`, the path name is misleading. The generic `/_next/hmr`
better reflects that this endpoint is bundler-agnostic.

## Changes

- **Client source** (`page-bootstrap.ts`, `web-socket.ts`): updated the
WebSocket connection path
- **Server** (`router-server.ts`): updated the HMR request detection
path
- **Turbopack** (`turbopack-dev-server/src/lib.rs`): updated the
fallback WebSocket path check
- **Tests**: updated all test files referencing the old path
- **Docs** (`version-12.mdx`): added a note that the path was renamed to
`/_next/hmr` in Next.js 16, while keeping the original v12 examples
intact
2026-03-19 16:39:45 +01:00
Zack Tanner a41bef94c5 improve allowedDevOrigins error (#91521)
This improves the blocked-request warning so it names the actual dev
resource being requested and gives clearer guidance on how to allow it.
When the source host is known, the message includes an inline
`allowedDevOrigins` config snippet; when the source is missing or
opaque, it explains why Next.js cannot infer a host to allow.
2026-03-17 17:35:29 -07:00
Zack Tanner b2b802c043 block disallowed dev origins by default (#91507)
This removes the warn-only default behavior and enforces the dev-origin guard by default. Cross-origin requests to internal dev resources now block unless they match the built-in local allowlist or an explicit `allowedDevOrigins` entry. The tests are expanded to cover default blocking, configured-but-not-allowlisted hosts, missing Referer in the no-cors path, and same-site requests without an Origin, and the docs are updated to match the new behavior.
2026-03-17 16:02:33 -07:00
Zack Tanner d0a0474d3d fix allowedDevOrigins for no-cors requests (#91506)
This PR makes configured `allowedDevOrigins` apply to cross-site no-cors dev asset requests. When browsers omit Origin for subresource loads, the dev guard now falls back to `Referer` so explicit allowlisted hosts can load `/_next/*` resources in development.

Previously, when `allowedDevOrigins` was configured, cross-site no-cors requests to internal Next.js dev resources were still blocked even for allowlisted hosts, because that code path never consulted the allowlist.
2026-03-17 13:57:40 -07:00
Zack Tanner 862f9b9bb4 Allow blocking cross-site dev-only websocket connections from privacy sensitive origins (#91479)
See:
https://github.com/vercel/next.js/security/advisories/GHSA-jcc7-9wpm-mj36
and [16.1.7](https://github.com/vercel/next.js/releases/tag/v16.1.7)

Co-authored-by: Sebastian "Sebbie" Silbermann <sebastian.silbermann@vercel.com>
2026-03-16 17:42:03 -07:00
Sebastian "Sebbie" Silbermann 672b02b270 [next-playwright] Use unique cookie values for instant navigation testing lock (#91250)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-03-16 21:07:56 +00:00
Tobias Koppers 1287f9a027 Turbopack: show specific SWC error messages as error titles (#91022)
### What?

Changes Turbopack's error overlay to show specific SWC diagnostic
messages as the error title instead of generic messages like "Parsing
ecmascript source code failed" or "Ecmascript file had an error".

### Why?

Previously, all SWC parse/analysis errors in Turbopack showed a generic
title (e.g. "Parsing ecmascript source code failed") in the redbox
header, with the actual specific error message buried in the description
below the code frame. This made it harder for developers to quickly
understand what went wrong.

**Before:**
```
Parsing ecmascript source code failed
> 1 | export default () => <div/
    |                           ^
Expected '>', got '<eof>'
```

**After:**
```
Expected '>', got '<eof>'
> 1 | export default () => <div/
    |                           ^
Parsing ecmascript source code failed
```

### How?

**Core change** in
`turbopack/crates/turbopack-swc-utils/src/emitter.rs`:

When the `IssueEmitter` has a `self.title` set (the generic title like
"Parsing ecmascript source code failed"), the SWC diagnostic message is
now used as the issue title, and the generic title is demoted to the
description. When `self.title` is not set, the existing behavior is
preserved (first line of message becomes title, rest becomes
description).

**Test updates** across ~15 test files:

Updated all `isTurbopack` branches in test expectations to reflect the
swapped title/description. Only Turbopack-specific branches were
modified; webpack and rspack expectations are unchanged.

**New test suite** (`test/development/app-dir/ecmascript-error-title/`):

Dedicated tests verifying that both syntax errors (e.g. `Expected '>',
got '<eof>'`) and analysis errors (e.g. `the name 'Table' is defined
multiple times`) show the specific SWC message as the redbox title.

**Turbopack snapshot updates:**

4 snapshot files renamed to reflect new titles (e.g. `Parsing ecmascript
source code failed-*.txt` → `Expression expected-*.txt`).

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-09 08:00:37 +01:00
Tobias Koppers 891cfe69c8 Turbopack: Add Next.js version to "initialize project" trace span (#90545)
## Summary

Adds the Next.js version as a `version` field on the Turbopack
"initialize project" tracing span. The version is passed from the
TypeScript side (`process.env.__NEXT_VERSION`) through the NAPI bindings
into Rust `ProjectOptions`, where it is recorded on the span.

This makes it easy to correlate trace data with the specific Next.js
version that produced it.

Also standardizes all version reads in `packages/next/src/` to use
`process.env.__NEXT_VERSION` (which is inlined at build time by
`taskfile-swc.js`) instead of `require('next/package.json').version` or
`import { version } from 'next/package.json'`.

### Changes

**Trace span (commit 1):**
- **`crates/next-api/src/project.rs`** — Added `next_version` field to
`ProjectOptions`; recorded as `version` on the `"initialize project"`
span
- **`crates/next-napi-bindings/src/next_api/project.rs`** — Added
`next_version` to `NapiProjectOptions` and wired it through the `From`
impl
- **`crates/next-build-test/src/main.rs`** — Added `next_version` to
test `ProjectOptions` init
- **`packages/next/src/build/swc/generated-native.d.ts`** — Added
`nextVersion` to the TypeScript `NapiProjectOptions` interface
- **`packages/next/src/server/dev/hot-reloader-turbopack.ts`**,
**`packages/next/src/build/turbopack-build/impl.ts`**,
**`packages/next/src/build/turbopack-analyze/index.ts`** — Pass
`nextVersion: process.env.__NEXT_VERSION` when creating the Turbopack
project
- **`test/development/basic/next-rs-api.test.ts`** — Added `nextVersion`
to both `createProject` call sites

**Consistent `__NEXT_VERSION` usage (commit 2):**
- **`packages/next/src/server/dev/hot-reloader-shared-utils.ts`** —
`require('next/package.json').version` → `process.env.__NEXT_VERSION`
- **`packages/next/src/lib/patch-incorrect-lockfile.ts`** —
`nextPkgJson.version` → `process.env.__NEXT_VERSION`; narrowed import to
only `optionalDependencies`
- **`packages/next/src/telemetry/events/swc-load-failure.ts`** — `import
{ version as nextVersion }` → `process.env.__NEXT_VERSION`; narrowed
import to only `optionalDependencies`

## Test Plan

- Verified Rust compilation with `cargo check -p next-api`, `cargo check
-p next-build-test`
- Verified TypeScript types with `pnpm --filter=next types`

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-26 18:37:15 +01:00
Sebastian "Sebbie" Silbermann 7d98e0b534 [test] Include error code in Redbox snapshot (#90497) 2026-02-26 11:01:25 +00:00
Will Binns-Smith aac4ebb7ac Turbopack: Server HMR infrastructure (#88870)
This adds some basic JavaScript/TypeScript infrastructure for Next to receive and handle server-side HMR updates from Turbopack.

This:
- Renames some existing hmr code as explicitly client hmr
- Adds counterpart apis for server hmr (e.g. subscribe to server HMR events via `project.serverHmrEvents()`)
- Add `__turbopack_server_hmr_apply__` runtime function (this is a stub for now, just logs on updates)

**Alternatives considered**
A single firehose for hmr events, pushing the filtering to the JS side. I figured separate dedicated apis would be cleaner since they’d have to be filtered and switched on anyway.

**In future PRs**
- Rust: Make Turbopack send 'partial' updates for server file changes
- Node dev runtime: Implement module factory replacement in `__turbopack_server_hmr_apply__`
- add client notification to trigger re-fetch of rsc
- e2e tests
2026-02-10 12:20:52 -08:00
Niklas Mischkulnig a2ee2d5830 Turbpopack: fix is_persistent_caching_enabled (#89533)
The next config setting was renamed, so this was always false.

So far, this was only used for telemetry.
2026-02-05 21:37:05 +01:00
Sebastian "Sebbie" Silbermann 93cf074e38 [test] Move off of as much url.parse as possible (#87286)
`url.parse` is deprecated in favor of WHATWG URLs. 

Almost all tests don't actually test integration with `url.parse`.

The remaining places test integration with the Next.js request handler
which does accept `url.parse` values.

We may deprecate that specific signature in favor of accepting WHATWG
URLs instead.
2025-12-26 14:00:28 -07:00
Cong-Cong Pan aa8a243e72 feat: use Rspack persistent cache by default (#81399)
Rspack now enables persistent caching by default.

## Performance Comparison

### Pages Router

I benchmarked performance using this repo:
https://github.com/SyMind/chakra-ui-docs/tree/next-rspack to test the
Next.js pages router.

I tested the performance with the following steps:

1. Execute `pnpm run dev`
2. Wait for the server to be ready (indicated by the 'Ready' message)
3. Run curl on the root endpoint (/)

Each build was run 5 times, and the shortest time to reach "Compiled
successfully" was recorded.

Test environment: Apple M1 Pro CPU

| Tool | Build without cache | Build with cache | Dev without cache |
Dev with cache |

|-------------|---------------------|------------------|---------------------------------|----------------|
| Rspack | 3.8s | 2.6s | 1.7s | 3ms |
| Webpack | 14.0s | 4.0s | 7.8s | 3.2s |

### App Router

I benchmarked performance using this repo:
https://github.com/SyMind/shadcn-ui/tree/next-rspack to test the Next.js
app router.

I tested the performance with the following steps:

1. Execute `pnpm run dev` or `pnpm run build`
2. Wait for the server to be ready (indicated by the 'Ready' message)
3. Run curl on the root endpoint (/)

Each build was run 5 times, and the shortest time to reach "Compiled
successfully" was recorded.

Test environment: Apple M1 Pro CPU

| Bundler | Build (No Cache) | Build (Cache) | Dev (No Cache) | Dev
(Cache) |

|------------|----------------------|-------------------|--------------------|-----------------|
| Rspack | 12.3s | 5.9s | 7.1s | 1941ms |
| Webpack | 27.0s | 13.0s | 11s | 9.6s |

## About Rspack Persistent Cache Strategy

> packages/next/src/server/dev/hot-reloader-rspack.ts

Rspack's persistent caching differs from Webpack in how it manages
module graphs. While Webpack incrementally updates modules, Rspack
operates on complete module graph snapshots for cache restoration.

Problem:
- Next.js dev server starts with no page modules in the initial entry
points
- When Rspack restores from persistent cache, it finds no modules and
purges the entire module graph
- Later page requests find no cached module information, preventing
cache reuse

Solution:
- Track successfully built page entries after each compilation
- Restore these entries on dev server restart to maintain module graph
continuity
- This ensures previously compiled pages can leverage persistent cache
for faster builds

## Note

I have updated the test case configuration in
`test/integration/telemetry/next.config.use-cache` to disable persistent
cache.

This is because, whether using webpack or Rspack, when persistent
caching is enabled, modules are no longer recompiled by loaders, which
prevents the Telemetry plugin from collecting information.

Please note that this issue also exists with webpack. You can reproduce
it locally by running `pnpm run test
test/integration/telemetry/test/config.test.js` twice.
2025-12-17 20:24:48 -08:00
Cong-Cong Pan affb52dafc chore: update rspack 1.6.5 (#86853)
update @next/rspack-core version to 1.0.2 and update the snapshot

other changes:

- packages/next/src/build/webpack-config.ts
Adjusted configuration to account for differences in default node config
between Rspack and Webpack.

- packages/next/src/shared/lib/format-webpack-messages.ts
Added a fallback to moduleIdentifier in cases where Rspack does not
correctly populate moduleName.
2025-12-17 05:07:52 +00:00
Tobias Koppers f7b7f3c14f Turbopack: add NEXT_TURBOPACK_WRITE_ROUTES_HASHES_MANIFEST to write hashes into manifest (#86257)
### What?

Add an env var to write route hashes into a diagnostics file.
2025-11-20 22:47:20 +01:00
Sebastian "Sebbie" Silbermann 0b58a32c45 [test] assert* -> waitFor* when the util is not instant (#85450) 2025-10-30 14:44:08 +01:00
Sebastian "Sebbie" Silbermann cfe8c602f9 [test] Regenerate tsconfig.json files (#85515) 2025-10-30 10:09:23 +01:00
Benjamin Woodruff 40f48ebb5e Turbopack: Remove redundant log line, increase delay for compiling log message (#85133)
We've already got output logging for this stuff, and the "compiling" message is too noisy.

Only print `Compiling /...` it if the compilation takes more than 3s, stop printing `Compiled in` altogether.

After this PR:
<img width="1075" height="335" alt="Screenshot 2025-10-20 at 3 15 59 PM" src="https://github.com/user-attachments/assets/34e87d18-8feb-4470-ae11-0d8e4b3a8a6b" />

Removes this line:
<img width="1095" height="254" alt="Screenshot 2025-10-20 at 3 17 56 PM" src="https://github.com/user-attachments/assets/76fb795e-760a-4782-889a-dd98bcf09125" />
2025-10-20 22:53:45 -07:00
Zack Tanner 20cf4c07da add new devtools indicator loading state (#85083)
This removes the Next logo animation/dimming and replaces it with more
explicit states. We also use this UI to show when caches are being
warmed (when using Cache Components). When caches are being bypassed in
DevTools, we also will show this in the indicator with warning text,
indicating that we cannot accurately reflect what can be statically
prerendered.



https://github.com/user-attachments/assets/665d4f8b-8c01-4def-a60e-bc4ecdd1f879
2025-10-20 12:42:43 -07:00
Jiwon Choi d540fbd3e6 Deprecate Middleware API and add Proxy API (#84764)
Following up on https://github.com/vercel/next.js/pull/84119, this PR
deprecated the user-facing middleware API and added a replacement Proxy
API.

---------

Co-authored-by: JJ Kasper <jj@jjsweb.site>
2025-10-14 20:09:14 +02:00
Sebastian "Sebbie" Silbermann 6feaddf73e Remove unused eslint-disable directives (#84797)
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
2025-10-12 23:17:08 +02:00
Jiwon Choi c388db43dc CI: Enable experimental.isolatedDevBuild for test-dev (#84562)
Enabling `experimental.isolatedDevBuild` required many changes to the
current workflow, so we will incrementally roll out to the tests.

Enabling on test-dev instead of test-experimental-dev because
`-experimental` CIs are filtered via `experimental-tests-manifest.json`
and they don't cover all tests. We want to enable this feature by
default so we should ensure this incremental rollout is covered on all
test cases.

The flag was enabled for `test-experimental-dev` at
https://github.com/vercel/next.js/pull/84099, and this PR moves the flag
to the `test-dev` job.

1. ~~test-experimental-dev
([link](https://github.com/vercel/next.js/pull/84099))~~
2. test-dev (here)
3. test-prod
4. test-integration
5. test-unit
6. Enable by default, remove the flag, and update the rest

x-ref: https://github.com/vercel/next.js/pull/84043
2025-10-07 00:44:08 +02:00
Joshua Hannaford df6aed34f0 fix(Turbopack): Add better error messaging for when we can't determine Next.js root (#83918)
## Improve error message when Next.js package can't be found

### What?
Enhances the `get_next_package` function to provide a more informative
error message when the Next.js package cannot be found from the context
directory.

### Why?
When users encounter issues with Next.js package resolution, the
previous generic error message "Next.js package not found" didn't
provide enough context or guidance on how to fix the problem. The
improved error message explains potential causes and solutions.

### How?
- Updated the function to use Vc<FileSystemPath> for context_directory
- Improved error handling with a detailed message that:
  - Explains the issue clearly
  - Shows the context directory path where resolution failed
  - Suggests setting `turbopack.root` in the Next.js config
  - Mentions potential issues with symlinks
  - Provides a link to documentation for more information

### How to Test

To test this, 
1. Modify `<projectRoot>/bench/basic-app/next.config.js` to 
    ```js
    module.exports = {
      experimental: {
        serverMinification: true,
      },
      turbopack: {
        root: __dirname,
      }
    }
    ```
2. Run `pnpm build && pnpm swc-build-native` to ensure that you have the
updated code
3. Run `pnpm next dev --turbo bench/basic-app` and ensure the error
shows up exactly once
4. Run `pnpm next build --turbo bench/basic-app` and ensure the same
error shows up exactly once

---------

Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
Co-authored-by: Luke Sandberg <lukeisandberg@gmail.com>
2025-10-06 19:43:58 +00:00
Tobias Koppers 2838b8b0a5 Turbopack: add test case that checks memory leak (#83849)
### What?

add test case for memory leak
2025-09-19 10:20:32 +02:00
Niklas Mischkulnig de4f2f03bb Enable more tests for Turbopack, II (#83600) 2025-09-09 11:45:12 +02:00