## Summary
Adds an off-by-default `experimental.agentFeedback` workflow for
collecting Next.js friction without interrupting the user’s task.
- `next dev` writes a small managed block to the project
agent-instructions file.
- Agent entry points, including `next-dev-loop`, queue possible issues
instead of opening duplicate forms.
- At the final stopping point, an internal command checks the remote
gate and returns the reporting protocol bundled with that Next.js
version. The agent attempts to anonymize each qualifying issue and opens
a separate review form once. If the browser does not open, it prints the
URL for the user without troubleshooting the failure.
- Report links no longer contain a public page token. Nothing is sent
until the user submits the form, which remains rate-limited and uses a
server-only ingest credential.
- Disabling `agentFeedback` or `agentRules` removes only its managed
block on the next `next dev`. Empty generated agent files are cleaned
up; user-authored content is preserved.
- Adds API references for both options and updates the AI agents guide.
Bundling the protocol keeps the managed block small and allows the
report format to evolve with each Next.js version. The receiving form is
implemented in
[vercel/front#85739](https://github.com/vercel/front/pull/85739) and
should deploy before this workflow is enabled.
## Verification
- `NEXT_SKIP_ISOLATE=1 pnpm test-dev-turbo
test/development/app-dir/agent-rules-auto-generate/agent-rules-auto-generate.test.ts`
- `pnpm jest packages/next/src/server/lib/generate-agent-files.test.ts
packages/next/src/cli/internal`
- `npx eslint --config eslint.config.mjs
packages/create-next-app/helpers/generate-agent-files.ts
packages/next/src/server/config-shared.ts
packages/next/src/server/lib/generate-agent-files.ts
test/development/app-dir/agent-rules-auto-generate/agent-rules-auto-generate.test.ts`
<!-- NEXT_JS_LLM -->
### 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 -->
Fixes
```
[17:03:12] ncc_mswjs_interceptors failed because [tsl] ERROR in /home/runner/work/next.js/next.js/packages/next/src/server/og/cache-image-response.ts(27,17)
TS2307: Cannot find module 'next/dist/compiled/@vercel/og/index.node.js' or its corresponding type declarations.
```
--
https://github.com/vercel/next.js/actions/runs/31515393262/job/93859146712#step:8:723
Now we use externalize the `Promise.withResolvers` polyfill to allow
running `ncc` before we built `dist`.
[`httpxy`](https://github.com/unjs/httpxy) is a faster and actively
maintained variant of `http-proxy`. It also doesn't need any manual
patches to avoid security vulnerabilities in Next.js.
`httpxy` is used by Nuxt and maintained by the Nitro team.
The previous `@mswjs/interceptors` has a bug where the response it
forwarded never set the [`complete`
field](https://nodejs.org/api/http.html#messagecomplete). This wasn't an
issue so far (or not reported) but is an issue for `httpxy` which relies
on an accurate `complete` field.
Bumping `@mswjs/interceptor` now so that we can switch from `http-proxy`
to `httpxy`.
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
Add agentName to anonymous telemetry metadata
### What
Adds an agentName: string | null field to the anonymous telemetry
metadata block that accompanies every payload, alongside existing fields
like ciName, nextVersion, and isCI. The value is the detected AI coding
agent driving the process (e.g. claude, cursor, codex), or null when
none is detected.
### Why
We currently have no visibility into how much Next.js development
happens under AI coding agents. This field lets us understand that split
in the same anonymous way we already track other CLI usage.
### How
Agent detection via @vercel/detect-agent
- Vendored @vercel/detect-agent (from the Vercel CLI) into
`next/dist/compiled/@vercel/detect-agent` (new taskfile ncc task,
externals entry, and type declaration), matching how I *understand*
other third-party deps are bundled.
- The vendored detection method is async (it does a filesystem probe for
Devin in addition to env-var checks) and potentially slower than we'd
want for logging, so it's wrapped in a memoized helper:
`telemetry/agent-name.ts`. `getAgentName()` caches the promise from
`determineAgent()`: the first call runs detection once, concurrent
callers share that in-flight promise, and every later call resolves
against the already-settled result. The agent shouldn't change over the
process lifetime, so this is safe. Detection failures resolve to null so
telemetry never throws on this path.
Wiring into the payload
- `getAnonymousMeta()` is now async and includes `agentName: await
getAgentName()`. `storage.ts` awaits it on the send path (the record
method was thankfully already async).
- The NEXT_TELEMETRY_DEBUG=1 output now includes the meta block
alongside each event, so the full payload — including agentName — is
observable locally without sending anything. We didn't output this
before, so it was harder to debug these fields.
Consolidating agent detection
- There was a second, synchronous, hand-vendored copy of agent detection
(telemetry/detect-agent.ts) used only by the AGENTS.md/CLAUDE.md
auto-generation hook. It's been removed and that hook
(ensureAgentRulesForDev) now uses the same vendored `getAgentName()`.
Now we have a single source of truth and can easily get upstream changes
from the vercel CLI package. `ensureAgentRulesForDev` became async, its
only caller in start-server.ts was already in an async scope, so this is
easy.
### Testing
- NEXT_TELEMETRY_DEBUG=1 next build shows agentName in the payload meta
block next to ciName/nextVersion.
- Verified the memoized helper: agent present -> name; cleared env ->
null; repeated calls return the same promise instantly.
- agent-rules-auto-generate dev tests pass (agent-detected generates
files; cleared-env does not)
- next-server-nft trace snapshot updated: adds @vercel/detect-agent +
agent-name.js, removes detect-agent.js.
- ts, build, existing telemetry unit test, lint
Two related skills for the `next dev` agentic workflow. They're paired:
one establishes a shared session and view of the running app, and the
other builds on it for a specific kind of work.
**`next-dev-loop`** is the edit-then-verify rhythm during `next dev`.
After making a change, the agent needs to know whether it actually works
at runtime — not just whether it type-checks or compiles. The skill
teaches the agent to use the two views Next.js exposes about itself:
`/_next/mcp` (framework-side — routes, segments, RSC, server logs,
errors) and `agent-browser` (browser-side — DOM, console, network, React
fiber, vitals). The two views cross-check each other.
The preflight is the load-bearing part. It opens a headed
`agent-browser` session at the user's target URL with React DevTools
enabled, then pauses — because the page might be behind a login wall or
need specific state the user has to set up. Once the user confirms, the
agent probes `/_next/mcp`, confirms Turbopack, and pulls the route map.
Sibling skills can assume this setup is done.
**`next-ppr-optimizer`** is the first sibling. It's the agentic loop for
optimizing the static shell of a `cacheComponents` page: diagnose the
shell, pick the highest-ROI refactor, apply it, confirm the shell grew.
Two levers — push down (extract an I/O into a Suspense-wrapped child so
the parent stays static; autonomous for trivial cases) or cache (wrap in
`'use cache'` with a `cacheLife` profile chosen *with* the user — the
skill never invents one). Diagnosis uses the suspense tree +
`/__nextjs_original-stack-frames` for source resolution, with the H4
anti-pattern guardrail (one dominant boundary covering the viewport is
not a push-down candidate; recurse inside it instead).
<!-- NEXT_JS_LLM_PR -->
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.
**This is only sent if there is an explicit, user-provided
`--experimental-upload-trace` set.**
Adds two new attributes to the `start-dev-server` span when
`--experimental-upload-trace` is set:
- `rage-restart` — true if the server was restarted within 2 minutes of
last stopping
- `missing-next-dir` — true if the `.next` dir from the previous session
was deleted before restart
State (stop time + dist dir path) is written to a temp file outside
`.next` on graceful shutdown, so it survives `rm -rf .next`. Detection
results are passed to the child via `NEXT_PRIVATE_DEV_SPAN_ATTRS`,
following the same pattern as `NEXT_PRIVATE_ENABLED_FEATURES`.
Test Plan: Added an e2e test.
<!-- NEXT_JS_LLM_PR -->
---------
Co-authored-by: Will Binns-Smith <wbinnssmith@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
### What?
Adds `next internal upload-trace` CLI command for uploading CPU profiles
and Turbopack traces to Vercel Blob storage.
### Why?
When investigating performance issues, the Next.js team often needs CPU
profiles and Turbopack traces from contributors and bug reporters.
Currently there's no streamlined way to collect these files. This
command provides a single step to upload all profiling output after a
build.
### How?
- **`.next-profiles` directory**: CPU profiles
(`--experimental-cpu-prof`) and Turbopack traces (`--internal-trace`)
now write to `.next-profiles/` instead of separate locations,
consolidating all profiling output.
- **`next internal upload-trace [directory]`**: New CLI command that
uploads `.cpuprofile` files and `trace-turbopack` from `.next-profiles/`
to Vercel Blob via a secure handshake with an external API endpoint.
- Validates file headers before upload (JSON for `.cpuprofile`, binary
for `trace-turbopack`)
- Skips empty files
- Shows progress bar in TTY environments
- Groups all files under a single server-assigned session ID
- Only logs the session ID to the user (no internal blob URLs exposed)
- **`@vercel/blob` compiled**: Vendored into
`packages/next/src/compiled/@vercel/blob/` via ncc.
- **`--internal-trace` CLI flag**: Added to `next build` and `next dev`
to enable Turbopack tracing to `.next-profiles/trace-turbopack`.
- **Security**: The server controls the storage path (client only sends
filename), session continuity uses HMAC-signed tokens (stateless across
serverless instances), `allowOverwrite: false` prevents replacing
existing uploads, and filenames are validated against an allowlist.
- **Tests**: Added production test suite with a mock HTTP server.
Usage:
```bash
next build --experimental-cpu-prof --internal-trace
next internal upload-trace
```
Experimenting with the notion of a "bundled skill" — agent skills
shipped directly in the `next` package under `next/dist/skills/<name>/`.
The first bundled skill is `next-compile`, which calls the dev server's
`get_compilation_issues` MCP tool to check compilation errors. Bundling
(rather than shipping as a standalone plugin) fits here because the
skill is coupled to Next.js implementation details — the `/_next/mcp`
endpoint and the tool schema — so shipping it in lockstep with the
`next` version that exposes them keeps them in sync.
## What
Replaces the `@babel/code-frame` dependency with a new Rust-based implementation (`next-code-[frame](https://github.com/arthurprs/qfilter/pull/20#issuecomment-3986882055)` crate) for rendering code frames in error messages.
### Why
- **Crash fix**: `@babel/code-frame` uses the `js-tokens` library for syntax highlighting, which has [known issues](https://github.com/lydell/js-tokens?tab=readme-ov-file#known-failures) with large string literals and long lines. This can cause Next.js to throw RangeErrors when rendering errors, hiding the original issue!
- **Long line support**: The old implementation had no concept of terminal width, dumping entire lines into the output. The new implementation uses "horizontal scrolling" — truncating lines and centering the error location in the visible window.
- **Performance**: The Rust implementation only processes the visible line range (typically ~6 lines), not the entire file. Syntax highlighting uses a skip-scan heuristic to start tokenizing near the visible window rather than from byte 0.
- **Dependency reduction**: Drops the semi-unmaintained `@babel/code-frame` bundled dependency in favor of code we control.
### Benchmarks
In-process benchmarks comparing `render_code_frame()` (Rust, via criterion) against `codeFrameColumns()` (Babel, via hrtime with DCE prevention). Both have syntax highlighting and color output enabled. No process startup or file I/O is included in the measurement.
| Scenario | `next-code-frame` (Rust) | `@babel/code-frame` | Speedup |
|---|---|---|---|
| Small file (~490 lines TSX) | **5.4 µs** | 507 µs | **~94x** |
| Large file (~39k lines JS) | **143 µs** | 82.9 ms | **~580x** |
| Large file minified | **51 µs** | - | **-** |
The gap widens with file size because Babel's `highlight()` runs a regex tokenizer over the **entire source** before slicing to the visible window, while the Rust implementation uses a windowed line index and skip-scan heuristic — only processing the visible window regardless of file size. However, for minified files we do end up tokenizing the whole thing so we end up being only 8x faster
### How
- New `crates/next-code-frame/` Rust crate with:
- Frame rendering with terminal-width-aware horizontal scrolling
- Regex-based syntax highlighting (matching Babel's color scheme)
- Skip-scan heuristic for O(1)-ish highlighting regardless of file size
- Windowed line index that only scans/stores offsets for the visible region
- Comprehensive test suite (800+ lines)
- Exposed via both NAPI (native) and WASM bindings
- JS wrappers in `packages/next/src/shared/lib/errors/`:
- `code-frame.ts` — primary wrapper using native bindings
- `optional-code-frame.ts` — graceful fallback returning `undefined` if bindings are unavailable
- All existing callsites (`diagnosticFormatter`, `parseScss`, dev overlay, turbopack utils) updated
- for `patch-error-inspect.ts` i adopted an `injection` style approach to avoid coupling to the native dependency
### Concerns / review focus areas
- **Reliability**: The regex-based tokenizer is best-effort and language-agnostic — it should never crash on invalid syntax, but highlighting accuracy may differ from Babel's `js-tokens` in edge cases.
- **Native dependency**: This moves code frame rendering into the native binary. Performance should be better, but worth verifying there are no regressions in environments where native bindings behave differently (e.g. WASM fallback path).
- **Regressions**: The output format and color scheme closely match Babel's, but there may be subtle differences. The horizontal scrolling behavior is new.
Fixes#85357
Closes PACK-5754
AI coding agents often rely on outdated training data when working with
Next.js projects, leading to hallucinated APIs and deprecated patterns.
This PR addresses that by shipping version-matched documentation inside
the `next` npm package and generating agent instruction files during
`create-next-app`.
During `next` build, a new `copy_docs` task copies `docs/` from the repo
root into `dist/docs/`. Since `"dist"` is already in the package's
`files` array, the docs are automatically published at
`node_modules/next/dist/docs/`.
`create-next-app` gains a new `--agents-md` / `--no-agents-md` flag
(defaults to `true`). When enabled it writes two files:
- `AGENTS.md` — instructs agents to read `node_modules/next/dist/docs/`
instead of relying on training data
- `CLAUDE.md` — uses `@AGENTS.md` import syntax for Claude Code
The option appears in the recommended defaults display and is prompted
during the customize flow. Existing tests are updated with
`--no-agents-md` to avoid the new prompt.
i got bit by this often :p
<!-- 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
## 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 #
-->
## What?
Similar to `caniuse-lite` there's a new package in `browserslist` that
also has "data is outdated" message. In order to handle it in the same
way as `caniuse-lite` I've marked it external and added it as a
dependency of Next.js when installing.
I'm still not happy about this. This log is not super helpful and would
preferably be disabled. Alternatively we can switch to loading
browserslist using the rust-side browserslist implementation.
Warning message:
```
[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: `npm i baseline-browser-mapping@latest -D`
```
This implements `next experimental-analyze`, which generates bundle analyzer data without without writing chunks or other artifacts to disk. It also optionally serves the bundle analyzer so it can be browsed easily.
Examples:
`next experimental-analyze` - writes analyzer data and UI to `.next/diagnostics/analyze`
`next experimental-analyze --serve` - writes analyzer data and UI as well as serves the files on a static file server on localhost (by default on port 4000)
`next experimental-analyze --serve --port 4001` -- runs the above on port 4001
This adds an interactive Treemap-style bundle analyzer app to the Next.js codebase and writes a copy to disk when `next build --experimental-analyze` is run.
* It's a separate app in `apps/bundle-analyzer` as `@next/bundle-analyzer-ui` that uses `output: 'export'` to export a purely static Next.js app
* These static resources are copied into Next.js's published `dist` directory in the `next` package itself. Users never depend on `@next/bundle-analyzer-ui`
* When users run `next build --experimental-analyze`, these static resources are copied into the user's `.next/diagnostics/analyze` along with the data payloads needed to visualize the user's app
In an upcoming PR, we'll add `next experimental-analyze` that will create analysis files without build artifacts, as well as optionally start a static file server.
Test Plan: Ran `next build --experimental-analyze` in a test app and ran a static file server to run it.
This PR adds a two new options and sets a strict default value for each.
- `images.dangerouslyAllowLocalIP`
- `images.maximumRedirects`
### dangerouslyAllowLocalIP
In rare cases when self-hosting Next.js on a private network, you may
want to allow optimizing images from local IP addresses on the same
network.
However, this is not recommended for most users so the default is
`false`.
> [!NOTE]
> BREAKING CHANGE: This change is breaking for those who self-hosting
Next.js on a private network and want to allow optimizing images from
local IP addresses on the same network. In those cases, you can still
enable the config.
### maximumRedirects
Since are also testing redirects for local IPs, we can also reduce the
maximum number of redirects to 3 by default.
Unlike normal websites which might redirect for features like auth, its
unusual to have more than 3 redirects for an image.
In some rare cases, developers may need to increase this value or set to
`0` to disable redirects.
> [!NOTE]
> BREAKING CHANGE: This change is breaking for those who need image
optimization to follow more than 3 redirects.
## What?
Code-frame is used in the production server, this splits it off in it's
own package, reducing the amount of files that have to be traced for
production
This PR integrates an MCP server into the Next.js development server at
`/_next/mcp`, enabling AI agents to programmatically interact with
Next.js projects. We're including an initial `get_project_path.` tool as
an example that returns the project's absolute path - this serves as a
starting point to demonstrate how tools can expose project information
to MCP clients, with plans to expand the available tools for richer
AI-assisted development experiences.
In a previous PR https://github.com/vercel/next.js/pull/82118 we added a
fallback to `sharp().metadata()` when the magic number didn't detect the
image format in order to improve detection.
But `sharp` can be slow to read metadata, so we should avoid it if we
can.
So this PR uses the existing `image-size` package to detect the content
type in JS and only then does it fallback to the native `sharp` code if
necessary.
No tests were added since this doesn't change the behavior, only
performance.
In [satori 0.16](https://github.com/vercel/satori/releases/tag/0.16.0) release we removed the `satori/wasm` entrypoint and using the inline version, which means the wasm support can be sync now. This helps the bundle size get reduced and also we happily dropped the `init` method.
This helps us dropped `yoga-wasm-web` on `@vercel/og` side, which let us removed the patching in the precompile script
Closes NEXT-4534
This PR introduces the ability for next.js to forward logs, errors, and
unhandled rejections from the browser to the terminal the dev server is
running in (behind an experimental flag)
# Explanation
The 2 main components of this pr are the client side error accumulation
logic, and the ingest handling on the other side of the hmr socket.
We listen on the existing hmr socket to send batched logs, errors, and
uncaught rejections the frame after they were captured. All forwarded
data is sent with metadata so we can have reconstruct the log with an
equivalent level of information to the browser- since we expect AI
agents that can't access the browsers to be consumers of this feature
(and it's generally useful).
All foreign data created by the user in the browser is serialized using
`safe-stable-serializer`, a popular serializer [used by other logging
libraries](https://www.npmjs.com/browse/depended/safe-stable-stringify),
like
[pino](https://github.com/search?q=repo%3Apinojs%2Fpino+safe-stable&type=code)
(safety, determinism, fast). We also have a light shim on top of json
serialization to handle displaying custom data representations that
either wouldn't survive serialization (undefined) or we want to present
to users in a custom format (throwing proxies, promises, ...)
On the dev server server, we (bespoke) deserialize, source map, format,
and log. I tried to share as much logic as I could with error dev
overlay to avoid feature drift since they are very similar
implementations other than the render target
# Explicitly covered cases
- console table
- shows as `[browser]\n<table>\n(<source location>)`
- console trace
- shows as `[browser] arg1 arg2 ...\n<stack trace>\n([source mapped
location of log]`)`
- trace is source mapped
- ignored frames are shown, incase people explicitly want the full trace
- console dir
- shows as `[browser] arg1 arg2 ([source mapped location of log])`
- we need to explicitly capture stdout and rewrite it when we call nodes
`console.dir` to prefix and postfix with [browser] and and (`<source
mapped location of log>`) without adding newlines (we could do this for
console.table but it makes sense to keep the prefix and postfix on new
lines)
- console error
- `[browser] arg1 arg2 \n codeblock + source mapped stack of
console.error ([source mapped location of console.error])`
- if there are any `Error` values present we wont show the stack and
code block of console.error since it's overwhelming (this is fine since
we still tell the user where the `console.error` is with the appended
location)
- rejected promises that have `Error`'s
- behave identical to console.error, but is prepended with `⨯
unhandledRejection`
- the `Error`'s render with their source mapped stack + ignored frames
- no error stack can be automatically appended where the promise
rejected
- rejected promises that have non `Error` values
- prepended with `⨯ unhandledRejection: ${error.name}: ${error.message}`
- everything is logged in red
- no error stack can be automatically appended where the promise
rejected
- on caught error
- prepended with `Uncaught ${errorName}: ${errorMessage}`
- stack attached to error is source mapped + ignored frames are not
shown
- everything is logged in red but the code block of where the error
orginated from
- all other console cases
- shows as `[browser] arg1 arg2 ([source mapped location of log])`
- if an error is passed, we show the error name, message, source mapped
stack (colored white, ignored frames not shown), and code block if
available (syntax highlighted)
- we apply util.format to handle formatted strings
- logs captured during RSC rendering
- not piped to server, ignored on client
Closes NEXT-4534
When running `pnpm build` in the Next.js repo without an internet
connection, this currently fails while trying to download the AMP
`validator_wasm.js` file. We can fix this, and thus enable offline
support for `pnpm build`, by moving the download of this file from the
`precompile` task to the `ncc_amphtml_validator` task. The file is then
committed to `src/compiled/amphtml-validator`, and later copied into
`dist/compiled/amphtml-validator` as part of the build command, without
the need to trigger a request.
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
Now that `tsc` can be run repeatedly without erroring, we can run it in
watch mode during `pnpm dev` to ensure that type errors are always
up-to-date while developing. Previously, we had to restart `pnpm dev`,
like animals.
missed this one in #78916. Weirdly enough the replacement seems to be working fine -- i guess something in recast was parsing the string (i.e. `path.replace("__turbopack_load_by_url__")` worked somehow). but that's not allowed according to recast's types, so we shouldn't rely on that.