Commit Graph

22 Commits

Author SHA1 Message Date
Hendrik Liebau 3c4afc1a3a Run Cache Components dev validation on a worker thread (#96153)
This moves the dev-mode Cache Components validation renders off the dev
server's main thread onto a worker thread, so rapid navigation no longer
starves the event loop. The worker crosses into the app-page bundle
exactly once, calling a new
`ComponentMod.routeModule.runValidationInDev` entry that rebuilds the
render context, work store, and request store from a serializable
snapshot and runs the whole validation there, so the client prerender
and the user's client components resolve the single app-page React
instance rather than a second copy.

A thin worker shell (`dev-validation-worker.ts`) plus a single-worker
pool (`dev-validation-worker-pool.ts`) load the user bundle via
`loadComponents`, install code-frame support for CLI output, and forward
the validation errors back as Flight bytes; the main thread only
delivers them to the overlay through `sendErrorsToBrowser`. The
snapshot, the globalThis-symbol handoff, and the shared error-delivery
helpers live in their own modules. The dev server installs the worker
when `experimental.devValidationWorker` is not `false`, and
`runDevValidationInBackground` uses it when present, falling back to the
in-process path otherwise. A one-slot `SharedArrayBuffer` propagates a
supersede abort into the worker so a newer navigation cancels an
in-flight validation.

The runtime bundle gains an `app-worker` entry for the worker with the
`build/swc` boundary externalized for the code-frame native binding, and
`patch-error-inspect.ts` now backs its code-frame renderer with a
globalThis symbol so all copies of the module share it across the
thread.

The synthetic `bench/dev-validation` benchmark navigates back-to-back,
so every click lands inside the validation window — the worst case for
main-thread contention. Browser-observed navigation TTFB in that window,
worker vs in-process:

| Route  | Worker (p50/p95/max) | In-process (p50/p95/max) |
| ------ | -------------------- | ------------------------ |
| client | 19 / 24 / 27 ms      | 40 / 66 / 7762 ms        |
| server | 42 / 45 / 46 ms      | 122 / 158 / 252 ms       |
| sprite | 109 / 117 / 169 ms   | 196 / 208 / 299 ms       |

The steady-state difference is only tens of milliseconds; the effect
that matters is the tail. In-process, a navigation that collides with an
in-flight validation render can stall for seconds (this run peaked at
~7.8s on the client route, and the peak varies run to run) because a
staged render does not yield until it finishes; off-thread the main
thread stays free and that stall disappears.

Read these as an upper bound, not a speedup that generalizes. The work
moved off-thread is the validation render's CPU — bounded,
route-dependent, and free of IO — so it does not grow with the main
render's cost. In an app whose main render is dominated by IO the same
absolute saving is a small fraction of the request, and it only appears
when a navigation lands in the brief validation window; at ordinary
click speed it is largely invisible. This is a dev-only responsiveness
improvement whose benefit varies widely with the app and the navigation
pattern.

As a follow-up, the validation work that still runs on the main thread
could move to the worker as well. When the main render can't be reused
for validation (for example after a cache miss), the validation
re-renders on the main thread to produce its inputs, resuming from the
Resume Data Cache (RDC) the main render already filled, and only then
hands the resulting Flight chunks to the worker. A later iteration could
run those renders inside the worker too, transporting the (serializable)
RDC so the worker can resume from the filled caches rather than reading
them back on the main thread.

closes NAR-895
2026-07-25 07:21:03 +02:00
Janka Uryga 0da4c2814f fix: work around SWC compress bug (#95457)
Works around a compiler bug in `SwcJsMinimizerRspackPlugin` that we
found in #95394

Some conditionals were getting miscompiled, from this:
```ts
if (inputsFromNavigation) {
  if (areStagesCompatible) {
    const instantInputs = needsInstantValidation ? inputsFromNavigation : null
    const staticInputs = inputsFromNavigation
    return { instantInputs, staticInputs }
  }

  if (navigationHasAppShell(navigationKind)) {
    const instantInputs = needsInstantValidation ? inputsFromNavigation : null
    const staticInputs = LAZY_RUNTIME_PRERENDER
    return { instantInputs, staticInputs }
  }

  const instantInputs = needsInstantValidation ? LAZY_FULL_RENDER : null
  const staticInputs = inputsFromNavigation
  return { instantInputs, staticInputs }
}
```
into this (in
`packages/next/dist/compiled/next-server/app-page-turbo.runtime.dev.js`)
```js
if (inputsFromNavigation)
  return areStagesCompatible || navigationHasAppShell(navigationKind)
    ? {
        instantInputs: needsInstantValidation
          ? inputsFromNavigation
          : null,
        staticInputs: inputsFromNavigation,
      }
    : {
        instantInputs: needsInstantValidation ? LAZY_FULL_RENDER : null,
        staticInputs: inputsFromNavigation,
      }
```
In the compiled version, the three branches get incorrectly merged into
two: if `navigationHasAppShell(navigationKind)`, static inputs are
`inputsFromNavigation` instead of `LAZY_RUNTIME_PRERENDER`. We're
guessing that this is a bug in some optimization of conditional returns;
disabling `compress.conditionals` in the minimizer seems to work around
it.
2026-07-03 16:03:38 +00:00
Cong-Cong Pan eacb749030 chore: upgrade next-rspack to rspack 2.0 (#92222)
## Summary
- upgrade `@rspack/core` to `2.0.0-rc.0`
- sync the in-tree next rspack Rust binding/toolchain with newer rspack
releases
- align Next server runtime selection so `NEXT_RSPACK` uses the
turbo-like app runtime path
- include missing compiled `@next/react-refresh-utils` output in
`ncc-compiled`

## What is done
- `@next/rspack` Rust binding builds locally
- `packages/next` builds locally
- rspack-related tests are running and have been reduced to deeper
runtime compatibility failures

## Rspack test investigation
Latest checked CI run: `build-and-test` run `27129243230` at head
`484e7bf1b30655a9f94d0855b9e00774b4b38cd0`.

Confirmed Rspack / webpack parity gaps:
-
`test/e2e/edge-runtime-configurable-guards/edge-runtime-configurable-guards.test.ts`:
Rspack does not expose the webpack parser hooks used by
`MiddlewarePlugin`. The current Rspack path falls back to SWC analysis
in `finishModules`, which can report diagnostics but cannot apply the
parser-time transforms that wrap `eval` / `new Function`, track
`InnerGraph` usage for used vs unused dynamic code, or apply
`unstable_allowDynamic` with webpack parity. Dev therefore misses the
expected dynamic-code runtime warnings and also reports false
`process.cwd` Edge warnings from Next internals; prod fails
allowed/unused dynamic-code cases.
-
`test/development/middleware-overrides-node.js-api/middleware-overrides-node.js-api.test.ts`:
same parser-hook limitation. Webpack can observe that `process.cwd` is
overwritten before use, while the Rspack SWC fallback statically flags
`process.cwd` as an unsupported Edge Node API.
- `test/production/css-features/css-compilation.test.ts`: the CSS is
minified and prefixed as expected, but the Rspack lightningcss path
currently does not expose/control source map generation the way this
test expects, so emitted CSS has no `sourceMappingURL` comment or `.map`
file to assert.
- `test/e2e/app-dir/server-source-maps/server-source-maps.test.ts`:
invalid source maps are not handled with the same graceful diagnostic as
webpack/Node source-map handling. Rspack logs the raw `webpack-internal`
frame for the damaged map case instead of surfacing the expected
`Invalid source map. Only conformant source maps...` message with the
cause.
-
`test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts`:
raw CI output observed a dev-mode timeout waiting for `networkidle`
after refresh/back/forward lazy fetching. This was not the final
structured failure in the latest run, but it remains a Rspack dev parity
follow-up around router cache lazy fetches and network settling.
- `test/e2e/middleware-src/middleware-src.test.ts`: after the test adds
root middleware files, Rspack dev still lets `src/middleware`
participate; the expected behavior is that only the root middleware
runs.
- `test/e2e/env-config/env-config.test.ts`: changing `.env` logs `Reload
env:` but the client keeps the previous `NEXT_PUBLIC_` value, pointing
at an Rspack dev env invalidation/HMR gap.
-
`test/e2e/app-dir/use-cache-without-experimental-flag/use-cache-without-experimental-flag.test.ts`:
after enabling the `useCache` flag, the dev server does not finish
restarting, pointing at build-error recovery/restart parity.
-
`test/development/app-dir/server-navigation-error/server-navigation-error.test.ts`:
middleware navigation-error cases hit `ERR_CONNECTION_REFUSED`,
consistent with the Rspack dev server exiting or restarting unexpectedly
during those error flows.
- `test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts`: the
custom-server dev process exits before the SDK handle is initialized,
then cleanup fails on `shutdown`; this needs follow-up in Rspack
dev/custom-server startup.
- `test/e2e/next-image-new/app-dir/app-dir.test.ts`: after toggling
image source, `onLoadingComplete` still reports the previous image
dimensions/source, pointing at an Rspack dev image/HMR or asset
invalidation parity issue.
- `test/e2e/node-cli-args/node-cli-args.test.ts`: on Node `20.19.x`,
`node --experimental-network-inspection` resolves instead of rejecting.
This looks like a Node-version behavior change rather than an Rspack
compiler issue.

Not attributed to this Rspack upgrade:
-
`test/e2e/app-dir/instant-navigation-testing-api/instant-navigation-testing-api.test.ts`
was marked by `scripts/pr-status.js` as a known flaky test across
branches.
-
`test/production/app-dir/build-output-prerender/build-output-prerender.test.ts`
ran in the webpack prod job and only differs by prerender error ordering
in the inline snapshot.


<!-- NEXT_JS_LLM_PR -->

---------

Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
2026-06-15 23:19:53 +00:00
Tim Neutkens ec28a4fdc6 Remove experimental.useNodeStreams flag as it's enabled (#93938)
### What?

Remove `experimental.useNodeStreams` from the public config surface and
make Node streams always-on for Node.js App Router rendering.

The smaller default-on change and dedicated CI cleanup landed in #94311.
The standalone compatibility update landed separately in #94347.

### Why?

Node streams are now the default Node.js runtime rendering path, so the
opt-in config and runtime selection plumbing are stale. Edge bundles
continue to use the web-stream path because Node streams are unavailable
there.

### How?

- Define `__NEXT_USE_NODE_STREAMS` as true for Node.js app runtime
bundles and false for edge user bundles.
- Remove config, schema, runtime, export, and server plumbing for
`experimental.useNodeStreams`.
- Delete the obsolete env-precedence fixture.
- Clean benchmark docs and scripts that still set or compare
`experimental.useNodeStreams`.

### Verification

- `pnpm --filter=next types`
- `pnpm build-all`

<!-- NEXT_JS_LLM_PR -->
2026-06-08 16:12:39 +02:00
Hendrik Liebau 608b569cb2 Bundle the 'use cache' deadlock probe worker (#93538)
Follow-up to #93500.

The probe worker (`use-cache-probe-worker.ts`) ships as plain `tsc`
output and `require()`s
`react-server-dom-webpack/server` directly. The merged PR added a
require-hook entry covering only that one specifier, which is not
enough. The vendored RSC binding itself does plain `require('react')`
and `require('react-dom')`, and with `--conditions=react-server` set on
the worker those fall through to the user's installed React. For any
Next.js app on React 18 that means React 18's `react.shared-subset`, a
stub that throws `"not yet supported outside of experimental channels"`.
The probe crashes the moment it spawns. Default canary tests didn't
catch this — their installed React 19 supports the `react-server`
condition — but running the suite with
`NEXT_TEST_REACT_VERSION="18.3.1"` surfaced it.

Adding more hook entries to cover `react`, `react-dom`, etc. would mean
manually mirroring the `${bundler} × ${reactChannel}` matrix that
`makeAppAliases` and the `react-server` layer rule in
`next-runtime.webpack-config.js` already encode for `react`,
`react-dom`, `react/jsx-*`, and
`react-server-dom-{webpack,turbopack}/*`.

The worker is now bundled through that pipeline as a new `'app-worker'`
bundleType, which inherits the alias matrix and is included in the
`react-server.node` layer rule. Four dev-only tasks (`{turbo,webpack} ×
{experimental,stable}`) produce the four artifacts. In
`use-cache-probe-pool.ts` when the pool is created we resolve the
matching bundle via `process.env.TURBOPACK` and
`needsExperimentalReact(nextConfig)`.

The worker source uses a plain static import of
`react-server-dom-webpack/server`, as we do everywhere else. The
require-hook entry is deleted, and `--conditions=react-server` is no
longer added to `NODE_OPTIONS` since all React specifiers resolve to
absolute paths at build time.
2026-05-06 15:58:59 +02:00
Hendrik Liebau e9b96b4128 Build with dev runtimes when --debug-prerender is set (#89834)
When running `next build --debug-prerender`, React owner stacks are now
captured and displayed in prerender error output. This makes it much
easier to diagnose which component triggered uncached I/O or accessed
request data without Suspense. Previously, `--debug-prerender` only
enabled source maps and disabled minification. Now it also auto-enables
`allowDevelopmentBuild` and sets `NODE_ENV=development`, which loads
React development builds where `captureOwnerStack()` is available.

The main challenge is that with `NODE_ENV=development`, both server and
client bundles include dev-only code paths (HMR, WebSocket connections,
dev overlay, debug channel, etc.) that expect a running dev server. We
don't want these when using `next start`. To solve this, we introduce
`process.env.__NEXT_DEV_SERVER`, an internal env var that is truthy only
during `next dev`. In client bundles, it's inlined at build time (`'1'`
for `next dev`, `''` for `next build`). In production server runtime
bundles, it's inlined as `''` for dead-code elimination. In development
server runtime bundles, it's left as a runtime check because those
bundles are shared between `next dev` (where it's set) and `next build
--debug-prerender` (where it's not). Meanwhile, `NODE_ENV` continues to
control React's dev/prod mode and error formatting, which is exactly
what we want for `--debug-prerender`.

This also replaces the previous `renderOpts.dev` / `workStore.dev`
pattern, which was unreliable because `RouteModule.isDev` was derived
from `NODE_ENV` at compile time. When `allowDevelopmentBuild` set
`NODE_ENV=development`, `isDev` would be compiled as `true` and
incorrectly activate all dev guards during `next start`.

Key changes:

- `config.ts` auto-enables `allowDevelopmentBuild` and sets
`NODE_ENV=development` when `--debug-prerender` is active
- `define-env.ts` inlines `__NEXT_DEV_SERVER` into all bundles (truthy
for dev, falsy for build) so dev-server features are dead-code
eliminated in production and `--debug-prerender` builds
- `next-dev.ts` and `next.ts` set `__NEXT_DEV_SERVER` in the process
environment for externalized server-side code
- `renderOpts.dev` and `workStore.dev` are removed — all consumers now
use `__NEXT_DEV_SERVER` (for dev-server features) or `NODE_ENV` (for
error formatting that should work in both dev and `--debug-prerender`
builds)
- `patch-error-inspect.ts` devirtualizes React server URLs in source map
URLs so they display as readable file paths
2026-02-13 16:29:10 +01:00
Hendrik Liebau dcd9be7aa1 [build] Remove layers experiment flag from next-runtime webpack config (#86126)
The `layers` feature is now enabled by default in Rspack.

<img width="1490" height="580" alt="layers-warning"
src="https://github.com/user-attachments/assets/42fd6575-f0d3-4249-a6b2-6073bbd7935d"
/>
2025-11-14 23:52:34 +01:00
Wyatt Johnson 50edb74488 [ppr] RDC for RSCs (redo) (#80853)
## What?

This PR introduces the Resume Data Cache (RDC) functionality to improve
handling of dynamic React Server Component (RSC) requests when Partial
Pre-rendering (PPR) is enabled. This enhancement enables dynamic RSC
responses to utilize the Resume Data Cache, significantly reducing
waterfalls and preventing content shearing.

## Why?

Previously, dynamic RSC requests with PPR enabled experienced several
issues:

**Waterfall Reduction:** Dynamic RSC responses required multiple
waterfalls to hydrate a given cache, leading to slower response times
and unnecessary network round-trips.

**Content Shearing Prevention:** There were mismatches between static
cached parts of the page and the dynamic response, causing visual
inconsistencies and potential hydration errors. By ensuring the RDC
generated for static responses is also used for dynamic RSC responses,
we maintain consistency even when the dynamic response interacts with
caches directly and potentially receives newer, non-stale values.

**Additional Issues Addressed:**
- Stale content revalidation not triggering correctly
- Background revalidation producing dynamic responses instead of static
ones
- Inconsistent cache tag staleness evaluation
- Missing support for resumable rendering in dynamic contexts

## How?

**Core Implementation:**
- Added Resume Data Cache layer that stores resumable render data for
dynamic RSC requests
- Ensures the same RDC used by static responses is reused for dynamic
RSC responses
- Introduced `forceStaticRender` flag to ensure background revalidation
generates static responses
- Refactored response cache internals to separate cache entry creation
from response handling
- Enhanced error handling with try-catch blocks for server actions in
app-render

**Revalidation Improvements:**
- Fixed cache tag staleness evaluation for consistent behavior
- Improved triggering logic for background revalidation of stale dynamic
content
- Better handling of cache misses and "no-resume-data" scenarios with
debug logging

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-08-29 11:27:06 -04:00
JJ Kasper 955adbb057 Remove extra base-server code (#81944) 2025-07-23 08:18:21 -07:00
Sebastian "Sebbie" Silbermann 16e1e1455e [node-webstreams] Use React builds for Node.js (#81048)
Closes https://linear.app/vercel/issue/NEXT-4560/

React now exposes Web stream APIs in their Node.js builds so we can use the Node.js builds.

That enable us to use some of the Node.js goodies like `async_hooks` which is required for the React's experimental Server Requests track.

## Test plan

`next-server` runtimes did not increase bundle size. We even saved some in the `app-page` entries since we no longer have to bundle Edge and Node.js versions of React Server. We can rely solely on the Node.js variant of React Server.

A build of `test/e2e/app-dir/hello-world` shows no significant bundle size changes
2025-07-02 07:53:34 +02:00
Sebastian "Sebbie" Silbermann 7957263139 [node-webstreams] Remove unused App externals from next-server bundler config (#81039)
These externals have no effect since we don't import the legacy `react-dom/server` APIs in `next-server` anyway.

We only import the modern APIs since we alias `react-dom/server` to `build/webpack/alias/react-dom-server-edge.js` which does not import from the legacy entrypoint.

## Test plan

- [x] `compiled/next-server` remained unchanged
2025-07-01 09:13:20 +02:00
Sebastian "Sebbie" Silbermann 0d7b49b1ca [dev-overlay] Move code into new top-level folder in src/next-devtools (#80281) 2025-06-11 16:51:14 +02:00
Sebastian "Sebbie" Silbermann ee94be90cd [dev-overlay] Use same bundle for Pages and App Router (#80019) 2025-06-07 15:46:56 +02:00
Sebastian "Sebbie" Silbermann 85c718fd65 [dev-overlay] Render /app Dev Overlay with a separate React instance (#79699) 2025-06-06 22:56:59 +02:00
Janka Uryga cb49b483f1 Reland "Ensure mangling is disabled for dev runtime builds (#75297)" (#79201)
Reapplies #75297

Also fixes some rspack tests which didn't await assertions properly so they might have looked like they're passing
2025-05-14 17:38:01 +02:00
JJ Kasper 62a3f91c1a Re-land updated bundler for pre-bundling (#79164)
Re-lands https://github.com/vercel/next.js/pull/75294 which uses rspack
for our prebundling of runtimes which can be slow when developing
locally.
2025-05-13 11:15:05 -07:00
Tim Neutkens 1d685d4b5d Turbopack build: Replace process.env.TURBOPACK usage (#77783)
Follow-up of #77762 as that was having too many conflicts as a similar
change landed last night.

<!-- 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

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### 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


## 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 #

-->
2025-04-03 20:16:22 +02:00
Hendrik Liebau 13f7ea4804 Optimize server runtime bundles (#77723) 2025-04-03 09:06:38 +02:00
Jiwon Choi 7085190f17 [dev-overlay] restructure dev-overlay project (#76291)
- Moved source files from `_experimental/` to `ui/`.
- Moved `dev-indicators` sources out of `internal/`.
- Renamed files and variables to have explicit `app-`, `App`, `pages-`
or `Pages` prefixes for better distinguish.
  - Updated snapshots that were caused by the name change.
- Added better type to `next-runtime.webpack-config.js`.
- Moved `font/` out of `ui/`.

---------

Co-authored-by: Jiachi Liu <inbox@huozhi.im>
Co-authored-by: Jimmy Lai <laijimmy0@gmail.com>
2025-02-22 01:45:09 +09:00
JJ Kasper 0be280dc79 Revert changing bundler for runtime bundle but keep externals fix (#75412)
This reverts the bundler change part while we investigate source map
issue but keeps the externals optimize preventing the runtime bundle
from inflating back to over `4MB`.

This reverts commit 98b0700e97
This reverts commit 04c3f0b29c
2025-01-29 16:50:31 +00:00
JJ Kasper 04c3f0b29c Update bundler for pre-bundling runtime (#75294)
This improves the build script quite a bit and makes dev editing much
faster. Also fixed excludes causing webpack/babel compiled packages to
be bundled into the runtime un-necessarily reducing from `10MB` ->
`1.2MB`.

Before: `Finished next_bundle in 9.67s`

After: `Finished next_bundle in 1.27s`

Validated here
https://github.com/vercel/vercel/actions/runs/12957911052/job/36147343396?pr=12914
2025-01-24 22:19:18 +00:00
Jiachi Liu d07422f931 chore: rename modules for better meaning and searching (#73067) 2024-11-22 12:58:14 +01:00