Commit Graph

1310 Commits

Author SHA1 Message Date
Sebastian "Sebbie" Silbermann 9662feb629 [fragment-scroll] Ensure hoisted elements don't break scroll-to-top on page navigations (#83108) 2026-02-14 14:42:31 +01:00
Niklas Mischkulnig f63be5da42 test: Isolate read-only-source-hmr test (#86721)
This was flakey with Turbopack:
```
Error: TIMED OUT: /New page/

404
This page could not be found.

undefined
    at check (/root/actions-runner/_work/next.js/next.js/test/lib/next-test-utils.ts:726:9)
    at Object.<anonymous> (/root/actions-runner/_work/next.js/next.js/test/integration/read-only-source-hmr/test/index.test.ts:124:7)
```

But somehow Webpack doesn't automatically refresh the page here?



https://github.com/user-attachments/assets/b363dbff-60d1-4813-bb1c-e5a64f0312d3
2026-02-14 11:08:12 +01:00
Tobias Koppers 740d55cdce Turbopack: Add inline loader configuration via import attributes (#89644)
## What?

Adds support for inline loader configuration in Turbopack via import attributes. Developers can apply webpack-compatible loaders to individual imports using the `with` clause, without needing global `turbopack.rules` configuration.

```tsx
import rawText from '../data.txt' with { turbopackLoader: 'raw-loader', turbopackAs: '*.js' }
import value from '../data.js' with {
  turbopackLoader: 'string-replace-loader',
  turbopackLoaderOptions: '{"search":"PLACEHOLDER","replace":"replaced value"}'
}
```

## Why?

Global `turbopack.rules` applies loaders to all files matching a pattern. This PR provides per-import granularity — useful when only a specific import needs special treatment, avoiding side effects on other imports of the same file type.

## How?

### Import attributes parsing (`turbopack-ecmascript/src/analyzer/imports.rs`)
- Extended `ImportAnnotations` to parse four new attributes: `turbopackLoader`, `turbopackLoaderOptions`, `turbopackAs`, `turbopackModuleType`
- All values are strings per TC39 import attributes spec (`turbopackLoaderOptions` is a JSON-encoded string)
- Added unit tests for the parser

### New structured loader type (`turbopack-core/src/loader.rs`)
- Added `WebpackLoaderItem` struct shared between inline and global loader paths

### Reference type plumbing (`turbopack-core/src/reference_type.rs`, `turbopack-ecmascript/src/references/esm/base.rs`)
- Added `ImportWithTurbopackUse` variant to `EcmaScriptModulesReferenceSubType` carrying the parsed loader, rename_as, and module_type
- ESM reference resolution maps the parsed annotations to this new subtype

### Loader execution (`turbopack/src/lib.rs`)
- In `process_default_internal`, detects `ImportWithTurbopackUse` references and applies the loader as a source transform via the existing webpack loader infrastructure
- Requires `enable_webpack_loaders` to be configured (same as global rules)
- Supports `turbopackAs` (re-processes with new extension) and `turbopackModuleType` (directly sets module type)
- Avoids infinite recursion by switching to plain `Import` reference type on re-processing

### Documentation (`docs/.../turbopack.mdx`)
- Added section documenting the four import attributes with examples
- Added version history entry for v16.2.0

### Testing (`test/development/app-dir/turbopack-import-assertions-use/`)
- E2e test covering raw loader, replace loader with options, `turbopackModuleType: 'ecmascript'`, and `turbopackModuleType: 'json'`
- Turbopack-only (skipped for webpack)
2026-02-13 19:45:10 +01:00
Tobias Koppers b05a35a79f Turbopack: Move turbopackIgnoreIssue from experimental to turbopack.ignoreIssue (#89817)
## What?

Moves the `turbopackIgnoreIssue` config from `experimental` to the stable `turbopack` config as `turbopack.ignoreIssue`.

## Why?

Reviewers on #89682 agreed the API is stable enough to graduate from experimental. Also addresses a docs wording suggestion.

## How?

- **TypeScript types**: Moved `ignoreIssue` field from `ExperimentalConfig` to `TurbopackOptions` in `config-shared.ts`
- **Zod schema**: Moved validation from `experimentalSchema` to `zTurbopackConfig` in `config-schema.ts`
- **Serialization**: Moved RegExp serialization logic into the turbopack block in `build/swc/index.ts`
- **Rust**: Moved `ignore_issue` field from `ExperimentalConfig` to `TurbopackConfig` in `next_config.rs`, updated the `turbopack_ignore_issue_rules()` method to read from `self.turbopack`
- **Tests**: Updated config in test to use `turbopack.ignoreIssue` instead of `experimental.turbopackIgnoreIssue`
- **Docs**: Removed `version: experimental`, updated all code examples, moved entry from experimental table to stable config list in turbopack.mdx, fixed "Good to know" wording to say "prefer using more specific `path` patterns" (since `path` is already required)
2026-02-13 14:56:59 +01:00
Niklas Mischkulnig 9e4e6d6f20 Turbopack: fix CSS dependency locations (#89761)
For some locations LightningCSS is 1-indexed (but not all of them, the rustdoc describes it though)
IssueSource is always 0-indexed

Previously, it looked like this
```
Error: Turbopack build failed with 1 errors:
./bench/basic-app/app/[variants]/styles.css:7:12
Module not found: Can't resolve './test1.png'
  5 | .style {
  6 |   cursor: url(./test1.png);
> 7 | }
    |  ^
  8 |
```
2026-02-13 12:01:32 +01:00
Will Binns-Smith b3774eaefb Trace upload: include experimental flag states (#89845)
This includes the set of experimental flag states in events sent to the
trace upload receiver when `--experimental-trace-upload` is set. It only
includes a subset of experimental flags (so things like the trace upload
flag itself isn't meaninglessly sent).

Since reporting is often limited to the scope of a single span, the flag
state attributes are denormalized and copied onto every descendent span.
Limiting the set of flags prevents this from being unnecessarily large.

Test Plan: Added `test/development` test and built an app and verified
these tags are sent with `NEXT_TRACE_UPLOAD_DEBUG`

---------

Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: Luke Sandberg <lukesandberg@users.noreply.github.com>
2026-02-12 12:47:05 -08:00
Will Binns-Smith db1ff7c6ec Turbopack: Implement server hmr in nodejs dev runtime (#89130)
This implements the remainder of functionality needed for Server HMR
(Fast Refresh).

How It Works

- Turbopack detects file changes in RSC modules
- Rust sends HMR update payloads to the Node.js runtime via the existing
chunk update system
- A Node-specific HMR client evaluates changed modules using shared HMR
runtime logic (extracted earlier in this stack)
- Only modified modules are re-evaluated. Unmodified modules retain
their state
- Next.js hot-reloader forwards updates to RSC workers, triggering
automatic re-renders in clients

Test Plan: Added an e2e test confirming that unaffected modules don't
get re-evaluated when others change.
2026-02-11 14:46:11 -08:00
Tobias Koppers adcac5dff1 Add turbopackIgnoreIssue config to suppress Turbopack warnings (#89682)
## What?

Adds the `experimental.turbopackIgnoreIssue` configuration option, which allows developers to suppress specific Turbopack warnings and errors based on file path, issue title, and/or description patterns. Filtered issues are hidden from both CLI output and the error overlay.

## Why?

Developers need a way to suppress noisy or expected warnings from Turbopack without disabling all warnings. This is useful for:
- Suppressing warnings from third-party code, generated files, or optional dependencies
- Reducing noise in development server output
- Hiding expected issues from the error overlay

## How?

### Configuration → Filtering Pipeline

1. **Config types** (`packages/next/src/server/config-shared.ts`, `config-schema.ts`):
   Each rule has a required `path` (glob string or RegExp) and optional `title`/`description` (exact string or RegExp). All specified fields must match (AND logic).

2. **RegExp serialization** (`packages/next/src/build/swc/index.ts`):
   Converts RegExp objects to `{ source, flags }` and glob strings to `{ type: 'glob', value }` for transfer to Rust.

3. **Rust deserialization** (`crates/next-core/src/next_config.rs`):
   `TurbopackIgnoreIssueRule`, `TurbopackIgnoreIssuePathPattern`, and `TurbopackIgnoreIssueTextPattern` types deserialize the config. A `turbopack_ignore_issue_rules()` turbo-tasks function converts them to `IgnoreIssue` rules with proper cache invalidation.

4. **Issue filtering** (`turbopack/crates/turbopack-core/src/issue/mod.rs`):
   `IssueFilter` is a turbo-tasks value that holds both severity filters and ignore rules. `IgnoreIssuePattern` supports exact string, glob, and regex matching (using `turbo-esregex` for ES-style regex). Matching issues are excluded before severity filtering.

5. **Integration** (`crates/next-api/src/project.rs`, `route.rs`, `empty.rs`):
   `Endpoint::project()` trait method provides access to the project config. `issue_filter()` builds the `IssueFilter` from project config. All issue collection points use the project's dynamic filter instead of the previous hardcoded `NEXT_ISSUE_FILTER`.

### Documentation

- New docs page: `docs/01-app/03-api-reference/05-config/01-next-config-js/turbopackIgnoreIssue.mdx`
- Updated Turbopack reference page with experimental options table: `docs/01-app/03-api-reference/08-turbopack.mdx`

### Testing

E2E test suite (`test/development/app-dir/turbopack-ignore-issue/`):
- **With config**: verifies matching warnings are suppressed from CLI output, matching errors are suppressed from the error overlay, and unrelated pages still compile normally
- **Without config**: verifies warnings and errors appear when no rules are defined

### Dependencies

- Added `turbo-esregex` for ES-style regex support in Rust

## Example

```js
// next.config.js
module.exports = {
  experimental: {
    turbopackIgnoreIssue: [
      { path: '**/vendor/**' },
      { path: 'app/**', title: 'Module not found' },
      { path: /generated\/.*\.ts/, description: /expected error/i },
    ],
  },
}
```
2026-02-11 08:26:58 +01: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
Will Binns-Smith 4d3ccd6ae0 Tracing: trace render times as render-path (#89763)
Analagous to the existing compile-path, which records compile times for
each path in development, we now record path render times as
`render-path`. It corresponds with the value we write to the tty when
rendering routes (e.g. `GET / 200 in 228ms (compile: 129ms, render:
99ms)`).

This change also adds tests for recording hmr data in the trace file.

Test Plan:
- CI
- Made changes in a test app and verified the trace file included valid
  entries for these. Confirmed the duration matched what was shown in
the cli.
2026-02-10 10:18:19 -08:00
Jiachi Liu 488d90d141 [test] consolidate the browser log test (#89601)
Filter out the extra logging from test env so we only assert on the
snapshot of forwarded logs
```
Snapshot name: `Terminal Logging (Webpack) App Router - Hydration Errors should show hydration errors with owner stack trace 1`

- Snapshot  - 1
+ Received  + 9

@@ -39,7 +39,15 @@
     6 |     <div>
  >  7 |       <p>{isClient ? 'client' : 'server'}</p>
       |       ^
     8 |     </div>
     9 |   )
-   10 | }
+   10 | }
+
+
+ [12:36:48.104Z] Browser Log: received ws message {"type":"isrManifest","data":{"/hydration-error":true}}
+
+ [12:36:48.104Z] Browser Log: Next.js page already hydrated
+
+ [12:36:48.109Z] Hydration complete for http://localhost:46145/hydration-error
  "
    at Object.toMatchInlineSnapshot (/root/actions-runner/_work/next.js/next.js/test/development/browser-logs/browser-logs.test.ts:317:33)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at processImmediate (node:internal/timers:449:9)
    at process.callbackTrampoline (node:internal/async_hooks:130:17)
```
2026-02-06 14:48:26 +01: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
Janka Uryga 812996cc60 [CC] Rename "unstable_prefetch" to "unstable_instant" (#89448)
Mostly mechanical rename.

Also changes the error page to `errors/invalid-instant-configuration`.
I'm not really worried about dangling links here because this is a new
API and we don't expect anyone to be using it yet.
2026-02-04 22:03:38 +01:00
Jiachi Liu 99c8038e33 Include owner stack for forwarded errors if available (#89493)
For forwarded logs, we can also attach the owner stack if it's
available, then we can see the proper errors trace shown in the
terminal.

In this way agent can directly detect where the error is happening from
reading terminal log, and fix it

| After | Before |
|:---|:---|
| <img width="937" height="778" alt="image"
src="https://github.com/user-attachments/assets/666cc012-4e79-41f4-9d6f-b9c1969316bf"
/> | <img width="942" height="641" alt="image"
src="https://github.com/user-attachments/assets/a44f795a-d297-4fb8-9efe-25e6e3684014"
/> |
2026-02-04 19:05:28 +01:00
Niklas Mischkulnig 37516d9579 Turbopack: improve suggestions for experimental.reportSystemEnvInlining (#89486)
Some better suggestions
2026-02-04 14:53:56 +01:00
Niklas Mischkulnig 43136958b4 Add experimental.reportSystemEnvInlining for Turbopack (#89304)
Part of PACK-6641

We don't have a way to silence (ignore-comment) warnings
And additionally, warnings in node_modules are always hidden...
2026-02-04 09:38:20 +01:00
Suhaib ef6ac79d0b feat: detect @typescript/native-preview as alternative TypeScript compiler (#89149)
## What?

This PR adds support for detecting `@typescript/native-preview` as an
alternative TypeScript compiler. When installed, Next.js will no longer
automatically install the `typescript` package.

## Why?

Fixes #88580

Users who want to use `@typescript/native-preview` (a Go-based native
TypeScript compiler) should not be forced to also install the
JavaScript-based `typescript` package. This is especially relevant for
projects using `next.config.ts` where TypeScript support is provided by
Node.js native TS or SWC.

## How?

1. Added `hasNativeTypeScriptPreview()` function to detect if
`@typescript/native-preview` is installed
2. Modified the dependency check logic in `verifyTypeScriptSetup()` to
skip auto-installing `typescript` when the native preview is present
3. Added an informative log message to notify users that some TypeScript
features (like type checking during build) require the standard
`typescript` package
4. Added e2e test to verify the behavior

## Test Plan

- Added new e2e test at `test/e2e/app-dir/typescript-native-preview/`
- The test verifies:
  - Detection message is shown
  - `typescript` is not auto-installed
  - The app still works (SWC/Turbopack handles compilation)
2026-01-30 15:38:14 -08:00
Hendrik Liebau f9173727f7 [test] Deflake browser-log-forwarding verbose level test suite (#89324)
[flakiness
metric](https://app.datadoghq.com/ci/test/runs?query=test_level%3Atest%20%40git.repository.id%3A%22github.com%2Fvercel%2Fnext.js%22%20%40test.name%3A%22browser-log-forwarding%20verbose%20level%20should%20forward%20all%20logs%20to%20terminal%22%20%40test.type%3A%22nextjs%22%20%40test.status%3Afail&agg_m=count&agg_m_source=base&agg_t=count&fromUser=false&index=citest&start=1769207121512&end=1769811921512&paused=false)

The test frequently failed because it snapshot-asserted on the forwarded
browser logs before the final debug message was forwarded. This is
because the initial assertion inside the `retry` block would pass
because it falsely matched the debug message inside the error code frame
(line 11):

```
[browser] browser error: this is an error message
    at Page.useEffect (app/page.tsx:10:13)
   8 |     console.info('browser info: this is an info message')
   9 |     console.warn('browser warn: this is a warning message')
> 10 |     console.error('browser error: this is an error message')
     |             ^
  11 |     console.debug('browser debug: this is a debug message')
  12 |   }, [])
  13 | (app/page.tsx:10:13)
```

By adding the `[browser] ` prefix to all expected log messages, we
ensure that the test only passes when the actual log messages are
forwarded, and not when they appear inside code frames.

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

-->
2026-01-30 23:07:14 +00:00
Jiachi Liu af18c32bc8 Improve lock dir error message (#89119) 2026-01-30 16:38:25 +01:00
Jiachi Liu f1a047fd80 IsolatedDevBuild flag removal (#89167)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: jiachi <jiachi@vercel.com>
2026-01-29 15:00:12 +01:00
Hendrik Liebau 5ec4d7a4be [Cache Components] Prevent streaming fetch calls from hanging in dev (#89171)
With Cache Components enabled in development, fetches without an
explicit cache config were incorrectly routed through
`createCachedPrerenderResponse` during the cache filling phase due to
the `serverComponentsHmrCache` condition. This function awaits the
entire response before returning to the caller, which prevents
infinitely streaming responses from ever being read or aborted.

This is a regression that was introduced in #84088.

These fetches should be treated as dynamic and use
`createCachedDynamicResponse` instead, which returns immediately and
caches in the background with proper error handling. The fix adds
`isCacheableRevalidate` to the condition so only explicitly cacheable
fetches use the blocking path.

Additionally, the "Failed to set fetch cache" warning is now suppressed
when the request's abort signal was triggered, since aborting is
intentional.
2026-01-28 21:53:56 +01:00
Benjamin Woodruff 7b2c80e24a Revert "Fix react-loadable-manifest chunk hash mismatch by preserving async loader mapping" (#89073)
Reverts vercel/next.js#88775

This is breaking the v0 marketing site, reverting to unblock.
2026-01-27 00:02:34 +00:00
Jiachi Liu bb88ea523d [mcp] change the mcp endpoint response to JSON (#88911) 2026-01-26 18:24:58 +01:00
Luke Sandberg e78d35b35d Fix react-loadable-manifest chunk hash mismatch by preserving async loader mapping (#88775)
## What?

Fixes a bug where `react-loadable-manifest.json` in Turbopack dev mode
contained references to chunk files with wrong hashes, causing 404
errors when loading dynamic imports.

## Why?

When using `next/dynamic` with nested imports (e.g., a dynamic component
that itself imports other modules), the chunk files referenced in
`react-loadable-manifest.json` had different hashes than the actual
generated chunk files.

The root cause was that `collect_next_dynamic_chunks` was
**recomputing** chunk content that was already computed by
`make_chunk_group`. This pattern was inherently brittle because Next.js
code had to carefully mirror Turbopack's internal chunking logic to get
consistent hashes.

This brittleness was exposed when the
`turbopackClientSideNestedAsyncChunking` feature was disabled in dev
mode (released in 16.1). The subtle differences in how availability info
was computed led to hash mismatches.

## How?

Instead of recomputing chunks for next/dynamic imports, this PR
preserves the module→async loader mapping from when chunks are first
computed in `make_chunk_group`, and looks up pre-computed chunks
directly. This eliminates the need for Next.js to replicate Turbopack's
chunking logic.

### Key changes:

1. **Extended `MakeChunkGroupResult` and `ChunkGroupResult`** with
`async_loaders_by_module` field
- Maps `ResolvedVc<Box<dyn ChunkableModule>>` → `ResolvedVc<Box<dyn
ChunkItem>>`
   - Preserves the module→loader relationship computed during chunking

2. **Eliminated redundancy** in `MakeChunkGroupResult`
- Removed the separate `references` field (was just upcasted async
loaders)
- Added `references()` method that derives references on-demand from the
map

3. **Simplified `collect_next_dynamic_chunks`**
   - Now performs simple lookup instead of recomputation
   - Removed `module_graph` and `chunking_context` parameters
- Uses `NextDynamicChunkAvailability` enum to access pre-computed chunk
groups

4. **Added regression test** to verify chunk files referenced in
manifest exist

### Files modified:
- `turbopack/crates/turbopack-core/src/chunk/chunk_group.rs` - Add
mapping, remove redundant field
- `turbopack/crates/turbopack-core/src/chunk/chunking_context.rs` -
Extend ChunkGroupResult
- `turbopack/crates/turbopack-browser/src/chunking_context.rs` - Pass
through mapping
- `turbopack/crates/turbopack-nodejs/src/chunking_context.rs` - Pass
through mapping
- `crates/next-api/src/dynamic_imports.rs` - Lookup instead of recompute
- `crates/next-api/src/pages.rs` - Updated caller
- `crates/next-api/src/app.rs` - Updated caller
- `crates/next-core/src/next_app/app_client_references_chunks.rs` -
Initialize empty map

Fixes #87680
2026-01-26 13:32:30 +01:00
Kim Dong Gyu 7eb2ea491e [Reapply] Add useEffectEvent to disallowed React APIs in Server Components (#88985)
<!-- 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?
Add `useEffectEvent` to the list of invalid React APIs in Server
Components.

### Why?
Using `useEffectEvent` in a Server Component results in a **runtime
error**: TypeError: (0 , react_1.useEffectEvent) is not a function.
Without this fix, developers only discover the mistake at runtime. This
change improves the **Developer Experience (DX) by catching the error
immediately in the IDE.**

#### Expected Behavior
<img width="999" height="566" alt="image"
src="https://github.com/user-attachments/assets/79c1cbf9-ae0e-4ad7-b163-f650fb289a3a"
/>

#### Currently
<img width="1708" height="805" alt="image"
src="https://github.com/user-attachments/assets/a33f73e5-24fd-4405-826a-53f1810154a7"
/>
<img width="2091" height="812" alt="image"
src="https://github.com/user-attachments/assets/ed3f191e-a34d-42dd-8779-1d524f6f035d"
/>

### How?
- Added `useEffectEvent` to Rust RSC transform
(`react_server_components.rs`)
- Added `useEffectEvent` to TypeScript constants (`constant.ts`)
- Added `useEffectEvent` to error formatting (`format-server-error.ts`)
- Added test fixture and updated test file

## Note

This is a reapply of the previous
[PR](https://github.com/vercel/next.js/pull/88950).
With help from @timneutkens, I all previously worked code to ensure
nothing was missed before resubmitting.

Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
2026-01-25 22:11:23 +01:00
Jiachi Liu 37ac3974db stabilize browser log forward options (#88857) 2026-01-22 12:11:53 +01:00
Sebastian "Sebbie" Silbermann 97532172c0 [test] Deflake test/development/app-dir/hydration-error-count/hydration-error-count.test.ts (#88749) 2026-01-19 19:09:07 +01:00
Sebastian "Sebbie" Silbermann a0e2d59cf4 [test] Deflake test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/verbose-level.test.ts (#88754) 2026-01-19 18:26:33 +01:00
Jiachi Liu 8cfdcacf37 Log browser error and warnings in terminal (#88352) 2026-01-16 15:10:24 +01:00
Jiachi Liu 0df959c1ab keep next-env.d.s unchanged between dev and build (#88428) 2026-01-14 13:51:22 +01:00
Tim Neutkens fd2bd2952e Move Ready in time before handler initialization (#88235)
## Move "Ready in X" log before config loading and eliminate duplicate
`loadConfig` calls

### What?

Reorder the dev server startup flow so the "Ready in X" log appears
before loading the user's `next.config.js`, and eliminate duplicate
`loadConfig` calls in both dev and build paths.

### Why?

Previously, the "Ready in X" time included the time spent loading and
evaluating the user's `next.config.js` file. This made the framework
appear slower than it actually is, especially for projects with complex
config files or slow config evaluation.

Additionally, config was being loaded twice:
- **Dev server**: Once in `getStartServerInfo()` just for logging, then
again in `getRequestHandlers()`
- **Build**: Once for the main build, then again in
`getStartServerInfo()` just for logging

### How?

**Before:**
```
1. getStartServerInfo() → loadConfig #1 (slow - blocks on next.config.js)
2. logStartInfo() → logs version, URLs, experimental features
3. "Ready in X" ← time includes config loading
4. getRequestHandlers() → loadConfig #2
```

**After:**
```
1. logStartInfo() → logs version, URLs, envInfo (no config needed)
2. "Ready in X" ← reflects actual framework startup time
3. getRequestHandlers() → loadConfig (once)
4. logExperimentalInfo() → logs experimental features
```

**Changes:**

- Split `logStartInfo` into two functions:
- `logStartInfo()` - basic info (version, URLs, env) - no config needed
  - `logExperimentalInfo()` - experimental features and cacheComponents
- Removed `getStartServerInfo()` which was loading config unnecessarily
- Added `experimentalFeatures` and `cacheComponents` to
`ServerInitResult` so they can be passed back after config loads
- In build, added `reportExperimentalFeatures` callback to the existing
`loadConfig` call instead of loading config twice

---------

Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
2026-01-08 19:09:50 +01:00
Tim Neutkens 41e3f93e36 Add experimental option to use no-cache instead of no-store in dev (#88182)
## What?

Adds `experimental.devCacheControlNoCache` to test `no-cache` vs
`no-store` for development.

Note: This is for testing only right now. If it's an improvement we'll
change the default.
2026-01-07 11:39:33 +01:00
Sebastian "Sebbie" Silbermann b821f423a6 Revert "dx: avoid next-env.d.ts change in dev" (#88153)
Reverting since it produced merge conflicts with in-progress
[strict-route-types
project](https://linear.app/vercel/project/nextjs-strict-route-types-2f0a70110d5d/overview):

The lesson learned from the earlier PR was that this is a risky change.
We'll land a similar change flagged in
https://github.com/vercel/next.js/pull/87768
2026-01-06 14:44:14 +01:00
Jiachi Liu 42493fb3a4 dx: avoid next-env.d.ts change in dev (#88103) 2026-01-05 14:35:33 +01:00
Jimmy Lai c74cb2ae25 Redesign default error pages with cleaner, more user-friendly UI (#87988)
- redesigns the default global + default error boundaries. removing the
WSOD forever :/
- adds dark mode support
- unifies a bit of the styling
- add the digest for the server error
- adds a return button on the client errors

<img width="3328" height="1914" alt="CleanShot 2026-01-02 at 09 46
36@2x"
src="https://github.com/user-attachments/assets/9994eb37-c22b-4847-9a18-e9acf0ae6236"
/>

<img width="2144" height="1242" alt="CleanShot 2026-01-02 at 09 47
01@2x"
src="https://github.com/user-attachments/assets/9b3bcf39-63f6-4c8d-85c5-2976c25f5b7b"
/>


<img width="2238" height="1632" alt="CleanShot 2026-01-02 at 09 47
17@2x"
src="https://github.com/user-attachments/assets/436433d7-9873-496a-9c96-536e070be9d7"
/>
<img width="1708" height="1260" alt="CleanShot 2026-01-02 at 09 47
23@2x"
src="https://github.com/user-attachments/assets/1ec42402-dbd9-41a3-801b-4745a4f128f7"
/>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 13:30:06 +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
Janka Uryga bf23890a91 [Cache Components] Fast setImmediate (#86018)
> This place is not a place of honor... no highly esteemed deed is
commemorated here... nothing valued is here.
> What is here was dangerous and repulsive to us. This message is a
warning about danger.

you think you know when setImmediate is supposed to run? no you don't

---

This PR introduces a patch to the Node `setImmediate` builtin. The patch
is enabled by calling
`DANGEROUSLY_runPendingImmediatesAfterCurrentTask()`. All immediates
scheduled after that point (until the end of the task) will be captured
and executed right after that task (after `process.nextTick` and
`microtasks`). This applies to immediates scheduled from immediates as
well.

This is relevant when scheduling back-to-back timeouts for staged
rendering in Cache Components:

```ts
setTimeout(() => {
  // runs first
  
  DANGEROUSLY_runPendingImmediatesAfterCurrentTask() // enable the patch
  setImmediate(() => {
    // runs second (normally, it'd run last!)
  })
})

setTimeout(() => {
  // runs third
})
```
the immediate scheduled from inside the first timeout will **always**
run before the second timeout.

A side-effect of this is that `setImmediate` will no longer be
considered IO in the Cache Components rendering model, because
immediates will always run before we advance the stage (or abort a
prerender), and thus can't result in a dynamic hole. This brings the
runtime behavior in line with React Devtools, which does not show
`setImmediate` as IO.

This patch also has some observable differences in behavior from native
`setImmediate`, mostly to do with uncaught errors:
1. sync errors in `process.nextTick` no longer interrupt
`processTicksAndRejections` (which would make us move onto the next
event loop step, and run the rest of the nextTick queue after the next
task, breaking our scheduling). They're rethrown in a microtask, which
changes the timing of `uncaughtException` a bit.
2. unhandled rejections will trigger `unhandledRejection` after _all_
fast immediates are done executing, not after each immediate. This
happens because our userspace immediate scheduling relies on nextTick,
and [rejections are only processed after everything else in
`processTicksAndRejections` is
done](https://github.com/nodejs/node/blob/d546e7fd0bc3cbb4bcc2baae6f3aa44d2e81a413/lib/internal/process/task_queues.js#L104-L105).

We hope that these divergences in behavior are niche enough to not
affect any real world code. Both are potentially fixable by managing our
own nextTick queue, more, but we'll try to avoid that complexity for
now.
2025-12-03 18:32:05 +01:00
Janka Uryga 1660d3966a [CC] Fix hanging dynamic promise when abandoning render (#86690)
Fixes #86662

The bug was introduced in #85747, where we added
`RenderStage.Abandoned`. We forgot to update the logic that rejects
promises on abort, so if a render was abandoned (i.e. restarted due to a
cache miss), then promises waiting for the dynamic stage would hang
forever.

This is not generally observable unless the promise is persisted/cached
in userspace. Userspace caches are problematic in Cache Components and
we discourage their usage, but the test app included here should still
work as expected (i.e. without hanging forever while rendering).
2025-12-02 15:11:15 +01:00
Jiachi Liu dcd0a60065 [devtool] unify the bundler field (#86514) 2025-12-01 17:02:33 +01:00
Hendrik Liebau 8303bbd460 Handle cross-page client reference contamination in development (#86591) 2025-12-01 14:21:24 +01:00
Jude Gao 52ea3cbabc Fix stale dev types causing build failure after route deletion (#86489)
When running `next dev`, then stopping it, deleting a route, and running
`next build`, the build would fail with a type error like:

```
.next/dev/types/validator.ts:78:39
Type error: Cannot find module '../../../app/simple-test/page.js'
```

The root cause here is a fundamental tension: we have **one
tsconfig.json** that needs to serve **two different modes**. When
`isolatedDevBuild` is enabled (which is the default), Next.js outputs
types to different directories:
- Development: `.next/dev/types/`
- Production: `.next/types/`

To avoid tsconfig.json changing every time you switch between dev and
build (which causes git noise and forces IDE reloads), we proactively
include both paths:

```json
{
  "include": [
    ".next/types/**/*.ts",
    ".next/dev/types/**/*.ts"
  ]
}
```

The problem is that TypeScript checks ALL files matching these patterns.
If `.next/dev/types/validator.ts` exists from a previous dev session and
contains imports to routes that have since been deleted, TypeScript
fails during build because those imports point to non-existent files.

You might ask: why not just completely separate them with two tsconfigs?
The issue is that would require users to know which tsconfig to use for
their IDE, and switching between configs manually defeats the purpose of
a seamless dev/build experience. The single tsconfig approach is
intentional.

The fix filters out `.next/dev/types` files programmatically when
running type check during build, without touching tsconfig.json:

```typescript
let fileNames = effectiveConfiguration.fileNames
if (excludeDevTypes) {
  const devTypesPattern = /[/\\]\.next[/\\]dev[/\\]types[/\\]/
  fileNames = fileNames.filter((fileName) => !devTypesPattern.test(fileName))
}
```

This way the tsconfig stays unchanged (no git churn, IDE stays happy),
dev types are preserved for concurrent dev sessions, and build only
type-checks its own `.next/types` directory.
2025-11-26 16:29:49 -05:00
Jiachi Liu 4d7d9abc08 [ts-plugin] keep showing the types in the function body (#86273) 2025-11-24 17:05:44 +01:00
Hendrik Liebau 36f50c5a11 Send dynamic validation errors to browser via WebSocket (#85818)
By sending the dynamic validation errors to the browser via WebSocket,
instead of rendering a validation outlet into the dynamic dev render
stream, we can avoid artificially delaying the spawned validation to
implicitly wait for the different chunks (static, runtime, and dynamic),
without blocking the dev render stream, and instead wait explicitly for
all chunks to accumulate.

Previously, we were using React's console replaying to get full fidelity
error stacks in the browser (including inspectable virtual server
modules). Now, we're using the same underlying mechanism by sending a
separate RSC stream through the WebSocket that contains only the errors.
In the browser, the received errors are then logged with
`console.error`, which also triggers that they're displayed in a
collapsed Redbox, as was the case before with the replaying.

---------

Co-authored-by: Janka Uryga <lolzatu2@gmail.com>
2025-11-21 16:10:15 +01: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
Janka Uryga 3f4db01dbc [Cache Components] Discriminate static shell validation errors by type (#85747)
Prior to this change any "hole" in a prerender that would block the
shell was considered an error and you would be presented with a very
generic message explaining all the different ways you could have failed
this validation check.

With this change we use a new technique to validate the static shell
which can now tell the difference between waiting on uncached data or
runtime data. It also improves the heuristics around generateMetadata
and generateViewport errors.

Added new error pages for runtime sync IO and ensure we only validate
sync IO after runtime data if the page will be validating runtime
prefetches.

Restored the validation on HMR update so you can get feedback after
saving a new file.

---

We've also discovered that hanging inputs are not handled correctly.
Fixing this is non-trivial and will be done in a follow-up, so for now,
we're disabling the failing tests.

---------

Co-authored-by: Josh Story <story@hey.com>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
2025-11-20 17:13:37 +01:00
Sebastian "Sebbie" Silbermann dc8f77375d Stop adding additional padding to Next.js logs (#86139) 2025-11-17 19:10:24 -08:00
Sebastian "Sebbie" Silbermann b3b97bc409 Allow attaching a debugger when next dev is already running (#86083) 2025-11-17 09:00:52 +01:00
Zack Tanner bf27e24aca fix: cacheMaxMemorySize should not disable dev HMR cache (#86164)
When configuring `cacheMaxMemorySize` to disable memory caching
(typically used for setups to adjust production caching behavior,
especially in multi-process self-hosted setups), this inadvertently also
disabled dev HMR caches which are intended as a performance
optimization. As a result of this, the dev console would be spammed with
"Single item size exceeds maxsize".

It's still possible to use this configuration to set a larger cache, but
otherwise it will have a minimum set to the previous default.

Fixes NAR-463
x-ref:
https://github.com/vercel/next.js/pull/85153#issuecomment-3429636751
2025-11-15 11:25:47 -08:00