Commit Graph

149 Commits

Author SHA1 Message Date
Niklas Mischkulnig bdbf63aef7 fix(next-custom-transforms): never place generated imports before directives (#98717)
## Summary

**What?** Fixes the error reported for a module that has a top-level
`"use client"` directive and an inline `"use server"` function
directive, e.g. `<form action={async () => { "use server" }} />` in a
client page.

**Why?** Under Turbopack this reported a bogus error — `The "use client"
directive must be placed before other expressions` — even though the
directive was already at the top of the file. The actual mistake (an
inline server action inside a Client Component) was never surfaced.

**How?** On Turbopack's RSC layer the server actions transform runs
*before* the React Server Components assert. When it hoists an inline
action it prepended its generated imports (`registerServerReference`,
action encryption, cache runtime) at index 0 of the module — *above* the
`"use client"` directive, which the transform does not consume. The RSC
assert then saw an import before the directive and reported it as
misplaced.

Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com>
2026-09-16 17:09:32 +02:00
Niklas Mischkulnig 538f3f68e9 Bump swc to v77 (#97407)
There have been breaking changes to the AST:
- `BlockStmtOrExpr` is now `ArrowFunctionBody`
- function bodies are `FunctionBody` instead of `BlockStmt`
- JSX text literals are `Wtf8Atom`, instead of `Atom`
2026-09-02 16:09:18 +02:00
Janka Uryga 55b26f96ab [PPF] Scaffold unstable_prefetch() (#97618)
Scaffolds a new API, `unstable_prefetch()`. It's only allowed in server
code, so we ban it from being imported in the client.
Implementation follows upstack. Intended to be merged together.
2026-08-21 13:50:23 +02:00
Niklas Mischkulnig 605425e139 Turbopack: rename to use turbopack: no side effects (#94427)
Consistent naming:
- `"use turbopack no side effects"`
- `"use turbopack: constants"`
2026-08-20 15:35:48 +02:00
Janka Uryga 2cc3694fda [PPF] Scaffold unstable_navigation() (#97236)
Scaffolds a new API, `unstable_navigation()`. It's only allowed in
server code, so we ban it from being imported in the client.
Implementation follows upstack. Intended to be merged together.
2026-08-20 15:27:11 +02:00
Hendrik Liebau cdf5c37d84 Scope app-entry export validation to files inside the app directory (#97350)
Adopts #97150. Closes #97150.

Fixes #96859

### What?

Since 16.3.0, builds fail for pages-router files named `sitemap` or
`robots` that export `getStaticProps`/`getServerSideProps`:

```
Error: "getStaticProps" is not supported in app/.
```

This is a regression from #94962, which added the metadata conventions
(`sitemap`, `robots`, `manifest`, `icon`, …) to the app-entry filename
regex in `ReactServerComponentValidator::assert_invalid_api`. The regex
only looks at the filename, so a file like `pages/sitemap.js` is now
mistaken for an app entry and rejected for exporting `getStaticProps`.

### How?

A file is only treated as an app entry when it's inside `appDir`,
reusing the gate `assert_server_filename` already applies to `error.js`.
The pages compilation context has no `appDir`, so pages-router files are
never validated as app entries.

On the test side:

- The fixtures that exercise the app-entry checks moved under
`app-dir/`, since the test harness derives `appDir` from the fixture
path. Their contents are unchanged.
- A new fixture (plus a `sitemap.js` fixture glob) asserts that a
pages-style `sitemap.js` compiles without errors.
- A new e2e suite, `test/e2e/pages-metadata-filenames`, covers
`pages/sitemap.js` with `getStaticProps` and `pages/robots.js` with
`getServerSideProps`. It fails without the fix under Turbopack (build
and dev) and passes with it under both Turbopack and webpack.

Supersedes #96873 (same approach, closed by its author) and closes
#96967.

---------

Co-authored-by: Rodrigo Arias <rodrigo@arias.me>
2026-08-14 11:53:24 +02:00
Hendrik Liebau c0c64a0ab1 Allow literal exports in 'use cache' files (#97181) 2026-08-12 06:42:24 +02:00
Hendrik Liebau 814135a843 Surface empty generateStaticParams as a redbox with a real stack (#95269)
Under Cache Components, a dynamic route whose `generateStaticParams`
returns an empty array is intentionally an error, but it surfaced badly:
in development the request failed with an uncaught error that left a
blank screen and a 500, and a production build printed the error without
a stack. The cause was that `throwEmptyGenerateStaticParamsError`
deliberately discarded the stack, because the throw happens in framework
code in `buildAppStaticPaths` after the user's function has already
returned, so there was no user frame to point at.

This change adds an SWC transform that gives the error a stack anchored
at the user's code. For a `page`, `layout`, or `default` file that
exports `generateStaticParams`, it emits a
`__next_create_empty_gsp_error` factory whose `new Error` is span-mapped
back to the source. It keys off the export rather than any declaration
named `generateStaticParams`, so it covers `export function`/`export
const`, `export { x as generateStaticParams }`, and `export {
generateStaticParams } from '...'`, while ignoring a same-named local
helper that is never exported. The anchor is the most specific
available: the `return []` literal when it is unambiguously the
function's only return, the declaration, or the export statement when
the body lives in another module. The transform is registered for both
bundlers, gated on Cache Components and excluded from the edge runtime,
mirroring the existing `debug_instant_stack` wiring.

At runtime the factory is attached to the segment as
`createEmptyParamsError` in `collectSegments`, and `buildAppStaticPaths`
throws it when it detects an empty result. Because the error now
originates in the page module rather than framework code, development
surfaces a proper redbox with a meaningful stack and production fails
the build with a stacked CLI error. The custom
`EmptyGenerateStaticParamsError` name has been dropped since it only
added noise to the logs. A few export forms, notably a wildcard `export
*` re-export, can't be detected from the page module alone, so when the
factory is absent the helper falls back to throwing the message with its
natural stack; those framework frames are ignore-listed in the output
but stay available for debugging.

The build-mode error does not yet include a code frame, because
`generateStaticParams` runs in the page-data worker, which lacks the
code-frame support that the prerender export worker has. That is left
for a follow-up. A new end-to-end test covers the redbox in development
for both a literal and a computed empty array, and asserts the per-route
build errors in production using `--debug-build-paths` so each route is
isolated. Transform fixtures cover the literal, computed,
preceding-statement, multiple-return, aliased-export, re-export, and
not-exported cases.
2026-06-30 11:18:53 +02:00
Josh Story d424aa8ec4 Stabilize unstable_instant (#94578)
This API has experimental modes for build validation but the dev
validation is going to be stable in the next release.
2026-06-09 13:50:25 -07:00
Matt Mastracci 908717af2d Drop once_cell from all direct crate deps (#93095)
## What

Purely mechanical change from once_cell to stdlib primitives.

---------

Co-authored-by: Luke Sandberg <lukesandberg@users.noreply.github.com>
2026-05-02 00:33:16 +00:00
Luke Sandberg 65542fa028 Reduce allocations in the next_debug_instant_stack transform (#93222)
This was allocating a regex on every transform, we can hoist that regex
up to avoid the work

I noticed this as a major source of temporary allocations in a dev
benchmark

also avoid a bunch of tiny string copies
2026-04-27 13:01:52 -07:00
Dmitrii cc5bbaad05 fix(server-actions): skip type-only ExportNamed in pre-pass to prevent phantom registerServerReference (#92494) 2026-04-13 15:50:44 +02:00
Luke Sandberg a24462d9e5 Replace wasmer with wasmtime for SWC plugin WASM engine (#91533)
## What?

Replace wasmer with wasmtime as the WASM runtime for SWC plugins.

## Why?

- Wasmer has been a source of build complexity due to conflicting feature flags (`wasmer/default` vs `wasmer/js-default`) and large binary size
- Wasmtime is actively maintained by the Bytecode Alliance with better performance and smaller footprint
- The upstream SWC project already provides `swc_plugin_backend_wasmtime` on crates.io, so we can use it directly instead of maintaining our own implementation

## How?

- Use the upstream `swc_plugin_backend_wasmtime` v9.0.0 crate from crates.io instead of a custom local implementation
- Replace `swc_core/plugin_transform_host_native` (which pulls in wasmer via `__plugin_transform_env_native`) with granular features: `__plugin_transform_host` + `__plugin_transform_host_schema_v1`
- Provide `WasmtimeRuntime` explicitly in both the NAPI bindings and turbopack plugin paths
- Remove all direct `wasmtime`/`wasmtime-wasi` workspace dependencies — the upstream crate manages its own wasmtime version
- Replace wasmer-related release profile size optimizations with equivalent wasmtime ones (`swc_plugin_backend_wasmtime`, `swc_plugin_runner`, `wasmtime`, `wasmtime-internal-cranelift`)
- Pin `vergen = "=9.0.6"` to avoid a `vergen-lib` version conflict with `vergen-gitcl` 1.0.8

## Binary size impact (darwin-arm64, compared against current canary)

| Metric | Canary | Wasmtime (this PR) | Delta |
|---|---|---|---|
| Unstripped dylib | 133.1 MB | 128.2 MB | **-5.0 MB (-3.7%)** |
| Stripped | 91.2 MB | 86.9 MB | **-4.3 MB (-4.8%)** |
| Stripped + gzip (npm) | 30.9 MB | 29.4 MB | **-1.5 MB (-5.0%)** |

<!-- NEXT_JS_LLM_PR -->
2026-04-09 09:34:00 -07:00
Aurora Scharff 108fe00fbd fix: replace docs/canary links with stable docs paths in error messages (#92528)
### What?

Error messages for the `"use cache"` directive and `after()` API (in
`cookies()`, `headers()`, `connection()`) pointed to `/docs/canary/...`
instead of `/docs/...`.

### Why?

On canary builds, `docs/canary` links can create circular or confusing
references. These APIs are stable and their docs live at the standard
`/docs/app/...` path.

### How?

Replaced all `nextjs.org/docs/canary/` URLs with `nextjs.org/docs/` in:

- `crates/next-custom-transforms/src/transforms/server_actions.rs` — the
`"use cache"` feature flag error
-
`crates/next-custom-transforms/tests/errors/use-cache-not-allowed/1/output.stderr`
and `2/output.stderr` — matching test fixtures
- `packages/next/src/server/request/cookies.ts`, `headers.ts`,
`connection.ts` — `after()` errors
- `packages/next/errors.json` — compiled error message index (6
occurrences)

<!-- NEXT_JS_LLM_PR -->
2026-04-08 20:28:46 +02:00
Jiwon Choi 66478522a8 Improve RSC error messages (#90702)
Improve the RSC error messages to be more comprehensive.

x-ref:
https://github.com/vercel/next.js/pull/89688#discussion_r2865847895

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-17 14:37:26 +01:00
Sebastian "Sebbie" Silbermann cb44b43cdf Use page extensions in next-swc transforms applying to pages (#90650)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
2026-03-04 16:13:36 +00:00
Josh Story 410c65808a Add static error when unstable_instant is used without cacheComponents (#90793)
`unstable_instant` requires `cacheComponents` to function — without it,
validation is entirely skipped and the config silently does nothing.
This adds a compile-time error in the SWC transform that catches the
misconfiguration early, matching the existing pattern used for segment
configs like `revalidate` that are incompatible with `cacheComponents`
(but inverted — `unstable_instant` requires it rather than being
incompatible with it). The error points directly to the export in the
user's source file.
2026-03-03 00:35:56 +00:00
Sebastian "Sebbie" Silbermann 4c6c31ad1e [instant] Don't add debug stack to random unstable_instant exports (#90273)
Instead of just limiting the transform to any file within the app dir, we now restrict it to any page, default, or layout file in the app dir. This avoids having the transform applied to random modules. The inserted value would not have been used by anything.
2026-02-27 10:17:52 +01:00
Luke Sandberg f93a867d77 Update wasm and next-custom-transforms crates to Rust edition 2024 (#90350)
The `wasm` and `next-custom-transforms` crates were still on Rust edition 2018 while the rest of the crates in this repo use edition 2024. This caused a pre-commit hook conflict:

- `cargo fmt` passes the crate's own edition (2018) to `rustfmt`, which uses **case-insensitive** import sorting
- The lint-staged pre-commit hook runs `rustfmt --edition 2024 --`, which uses **ASCII order** import sorting (uppercase before lowercase)

These two sort orders disagree on items like `{custom_before_pass, TransformOptions}` vs `{TransformOptions, custom_before_pass}`, causing an infinite flip-flop: every commit would reorder imports, and the next `cargo fmt` would reorder them back.

## Changes

- Bump `crates/wasm` and `crates/next-custom-transforms` from edition 2018 to 2024
- Add `+ use<C>` precise capturing to `server_actions()` return type to satisfy edition 2024's stricter `impl Trait` lifetime capture rules
- Add `style_edition = "2024"` to `.rustfmt.toml` as a safety net so `cargo fmt` uses 2024-style formatting regardless of individual crate editions
- Reformat all affected files with `cargo fmt`
- Apply new clippy rules
2026-02-23 01:48:12 -08:00
Sebastian "Sebbie" Silbermann 19dcd1339f [instant] Handle more instant declaration patterns (#90251)
Adds handling for 


```tsx
export { unstable_instant } from './config'
       ^
```
```tsx
const unstable_instant = ...
                         ^
export { unstable_instant }
```
```tsx
const instant = ...
                ^
export { instant as unstable_instant }
```
We're not following assignments recursively and stop at the first declaration:
```tsx
const _instant = ...
const instant = _instant
                ^
export { instant as unstable_instant }
```
2026-02-20 14:19:54 -08:00
Sebastian "Sebbie" Silbermann 8f231d6380 [instant] Include declaration location of instant config in validation errors (#90169) 2026-02-20 11:31:53 -08:00
Tobias Koppers c979cefa4a Turbopack: Enable tree-shaking for dynamic imports with destructuring (#89683)
## What?

This PR enables tree-shaking for dynamic imports when the imported module's exports are destructured or accessed via member expressions. Previously, dynamic imports were treated as importing all exports, preventing unused exports from being removed.

## Why?

Dynamic imports with destructuring patterns like `const { cat } = await import('./lib')` or member access like `(await import('./lib')).cat` now properly communicate which specific exports are actually used. This allows bundlers (particularly Turbopack) to tree-shake unused exports from dynamically imported modules, reducing bundle size.

## How?

### Core Changes:

1. **AST Analysis Enhancement** (`turbopack-ecmascript/src/analyzer/graph.rs`):
   - Added new `Effect::DynamicImport` variant that captures destructuring patterns and member access
   - Implemented `extract_dynamic_import_export_names()` to statically analyze destructuring patterns and extract used export names
   - Supports: const/let/var destructuring, renamed imports, nested destructuring, default exports, member access, and empty destructuring

2. **Export Usage Tracking** (`turbopack-core/src/resolve/mod.rs`):
   - Added `ExportUsage::NamedSet` variant to track multiple named exports being used
   - Updated `ModuleExportUsageInfo` to handle merging of multiple named exports

3. **Dynamic Import Reference** (`turbopack-ecmascript/src/references/esm/dynamic.rs`):
   - Extended `EsmAsyncAssetReference` with `export_names` field
   - Implemented `binding_usage()` to communicate which exports are used to the module graph

4. **Effect Processing** (`turbopack-ecmascript/src/references/mod.rs`):
   - Refactored dynamic import handling into dedicated `handle_dynamic_import()` function
   - Passes export usage information through the reference system

### Test Coverage:

- **E2E Tests** (`test/e2e/app-dir/dynamic-import-tree-shaking/`): Comprehensive tests for Next.js App Router covering various destructuring patterns
- **Snapshot Tests** (`turbopack-tests/tests/snapshot/basic-tree-shake/`): Turbopack-specific tests validating tree-shaking behavior

### Supported Patterns:

- ✅ Named destructuring: `const { cat } = await import('./lib')`
- ✅ Variable declarations: `var`, `let`, `const`
- ✅ Renamed imports: `const { cat: myCat } = await import('./lib')`
- ✅ Nested destructuring: `const { dogRef: { get } } = await import('./lib')`
- ✅ Default exports: `const { default: val } = await import('./lib')`
- ✅ Empty destructuring: `const {} = await import('./lib')` (side effects only)
- ✅ Member access: `(await import('./lib')).cat`

### Limitations:

- Rest patterns (`const { cat, ...rest }`) conservatively import all exports
- Computed property keys are not statically analyzed
- Member access tree-shaking is Turbopack-only (webpack limitation)

https://claude.ai/code/session_01QWi3udq2LX4GFqJEDaqFFU
2026-02-18 18:55:19 +01:00
Niklas Mischkulnig 1fac9a1b7e Upgrade to swc 56 (#89111) 2026-02-13 11:47:27 +01:00
Jiachi Liu 3aad67b75c feat: server action logging (#88277) 2026-01-16 15:09:02 +01:00
Niklas Mischkulnig 8cf1d1f1fa Upgrade to swc 54 (#88207)
Somewhat surprisingly, no breaking API changes

https://github.com/swc-project/swc/compare/v1.15.5...v1.15.8 tracks the changes
2026-01-07 23:30:29 +01:00
Janka Uryga c0d6a5d81e Guard against Object/Array shadowing in 'use cache' transform (#88229)
The transform output for 'use cache' uses `Object.defineProperty` and
`Array.prototype.slice`. In theory, it's possible for a module to shadow
those names and break it:
```ts
// i want to suffer!
const Array = {}
const Object = {}

async function cached() {
  "use cache"
  ...
}
```

We should defensively make sure that our transform's output refers to
the actual Object/Array builtins, not whatever's in scope for that name.
We can do this by using an unresolved syntax context for the
identifiers. This is what we do for `require()` elsewhere:
https://github.com/vercel/next.js/blob/6805af48baf1128e6b2a9e8f1752ee5982f02c60/crates/next-custom-transforms/src/transforms/track_dynamic_imports.rs#L119-L122
Using `quote_ident!(unresolved_ctxt, "Array")` will cause SWC to rename
any local redefinitions of `Array` to something that doesn't clash
(which can be seen in the added snapshots).
2026-01-07 19:04:15 +01:00
Hendrik Liebau 37a09be1d9 Omit unused arguments from 'use cache' function calls (#86920) 2026-01-07 16:12:38 +01:00
Tim Neutkens ae17e48bbf Update generateMetadata in client component error (#88172)
## What?

Improves the error shown when `generateMetadata` or `metadata` is
exported from a Client Component.

Also updated the documentation to further explain why it can only be
used in a server component and the steps to follow to resolve the error.
2026-01-07 09:45:44 +01:00
Benjamin Woodruff 9a1d04fb58 Turbopack: Update to swc_core v50.2.3 (#87841)
Update to swc_core v50.2.3 to address a parse issue with mdx files that should be fixed by swc-project/swc#11372:

- Fixes #87713
- Internal discussion: https://vercel.slack.com/archives/C04KC8A53T7/p1766716756273609?thread_ts=1766712717.419489&cid=C04KC8A53T7

I'm intentionally not updating to the latest SWC here to reduce risk, as I'd like to cherry-pick this into the Next 16.1 branch.

Changelog: https://github.com/swc-project/swc/blob/f9b4da2bd85d160b3ee4b3296ed520388675b90e/CHANGELOG-CORE.md#swc_corev5023---2025-12-15
2026-01-06 21:56:29 -08:00
Zack Tanner b1ce6042be add compilation error for taint when not enabled (#88173)
Using `taint` APIs from React without enabling `experimental.taint` will
error at runtime because it needs to bundle experimental React, making
it hard to catch and potentially leading to downtime. This updates our
transform to throw an error if we detect that it's imported but `taint`
isn't enabled.

Fixes NAR-690
2026-01-06 11:57:46 -08:00
Pyry Takala 653cf4af0c fix(next-custom-transforms): preserve all declarators in multi-declarator export statements (#86552) 2025-12-02 13:51:12 +01:00
Hendrik Liebau 3d30f407c4 Allow exporting object and array literals in 'use cache' files again (#86655)
In #86014 we added a validation for exporting object and array literals
from `'use cache'` files. This was a bit too restrictive, and
short-sighted, as it would prevent exporting common things like metadata
or viewport objects from page and layout files, if the file uses a `'use
cache'` top-level directive.
2025-12-01 10:01:11 +01:00
Hendrik Liebau 59fe222b5e Convert any export from a 'use cache' module to a cache function (#86014)
Previously, in a `'use cache'` module, we only compiled statically-known
exported functions and arrow expressions to cache functions. Now, we
also compile re-exports and exports of values that might be functions.

This includes exports like:
- `export { getData } from './data'` - re-exporting from another module
- `export const aliased = getData` - exporting an imported identifier
- `const Page = withSlug(...); export default Page` - exporting the
result of a function call

These cases can't be statically verified as functions at compile time,
so we generate runtime wrappers with `typeof === "function"` checks
(simplified):

```js
let $$RSC_SERVER_CACHE_getData = getData;
if (typeof getData === "function") {
    $$RSC_SERVER_CACHE_getData = React.cache(function() {
        return cache("default", "...", 0, getData, arguments);
    });
    registerServerReference($$RSC_SERVER_CACHE_getData, "...", null);
    Object.defineProperty($$RSC_SERVER_CACHE_getData, "name", { value: "getData" });
}
export { $$RSC_SERVER_CACHE_getData as getData };
```

This ensures that all function exports from `'use cache'` modules are
properly cached, while non-function exports pass through unchanged.

This approach comes with some limitations compared to statically-known
function exports:
1. **No compile-time type checking:** We can't verify that these exports
are actually functions. Non-function exports will be passed through
as-is at runtime.
2. **No async enforcement:** We can't enforce that functions must be
async (as we do for statically-known functions). Synchronous functions
are supported, but will lie about their type signature. They become
async after being wrapped as cache functions, even though their original
signature was synchronous.

closes NAR-196
2025-11-26 15:30:25 +01:00
Hendrik Liebau acac0b0567 Fix compilation of exported server functions (#86296)
With this PR we are restructuring how the Next.js compiler transforms server function modules (`'use server'` or `'use cache'` directive at the top of the file).

The workaround for skipping the registration of exported `'use cache'` functions is removed. All exported server functions are now properly registered during visitor traversal, which fixes incorrect server reference information bytes in server reference IDs in some circumstances (see #86292 for example).

We're also adding support for string literal exports, e.g.:

```js
'use server'

async function foo() {}
export { foo as '📙' }

```
2025-11-24 13:54:17 +01:00
Niklas Mischkulnig 33e1764252 Bump swc to 48 (#86240)
Upgrade swc from 45 to 48

Based on #85540

- In the AST, strings now contain a `Wtf8Atom` (= not utf8), while `Ident`s keep using the utf8 `Atom`.
- swc's comment printing logic also changed slighted, moving some comments around
- ~~Some comments are getting lost along the way and/or attached to the wrong line. This also broke server actions which rely on a `__next_internal_client_entry_do_not_use__` at the very top~~
2025-11-21 12:47:13 +01:00
Hendrik Liebau ee6e35a19e Omit unused encryptActionBoundArgs/decryptActionBoundArgs imports (#86015)
When a module does not include any `'use server'` or `'use cache'` closures that use variables from their outer scope, the imports for `encryptActionBoundArgs` and `decryptActionBoundArgs` are unnecessary.

> [!TIP]
> Review with hidden whitespace changes.
2025-11-12 11:19:09 +01:00
Hendrik Liebau ba20a5e8f2 Fix false-positive build error for cacheLife & cacheTag (#85875)
When functions exported from a module with a top-level `'use cache'`
directive are imported into client modules, the compiler should allow
`cacheLife` and `cacheTag` usage within those functions.

This PR updates the `react_server_components` transform to properly
track module directives (`'use client'`, `'use server'`, `'use cache'`)
and skip client graph validation for modules with `'use cache'`,
identical to how modules with `'use server'` are already handled. Those
modules are transformed anyway for the client graph by the
`server_actions` transform, which is applied after the
`react_server_components` transform, in which their implementation is
replaced by server function references.

closes NAR-498
2025-11-11 17:30:41 +01:00
Hendrik Liebau 5bd7c6fec0 [test] Add missing test fixtures for cacheLife & cacheTag in client (#85872)
Importing `cacheLife` and `cacheTag` in Client Components yields build errors. This adds test fixtures to cover these scenarios.

In addition, we're duplicating the test fixtures that have different error messages between `app/` and `pages/` directories to ensure both cases are covered.
2025-11-11 14:37:43 +01:00
Hendrik Liebau b6a7714057 Hoist inner 'use cache' functions to reduce function allocations (#85904)
This PR fixes a slight performance regression introduced in #85519 where
inline async function expressions were created for each unique set of
arguments passed to a `'use cache'` function.

For a function like this:

```js
export async function getCachedData(id) {
  'use cache';
  return fetch(`/api/data/${id}`);
}
```

we were previously generating (simplified):

```js
export var $$RSC_SERVER_CACHE_0 = cache("default", "0815", 0, async function(id) {
  return fetch(`/api/data/${id}`);
});
```

In #85519, we restructured this to ensure proper stack frames in error
messages (simplified):

```js
export var $$RSC_SERVER_CACHE_0 = React.cache(function getCachedData() {
  return cache("default", "0815", 0, async function(id) {
    return fetch(`/api/data/${id}`);
  }, arguments);
});
```

However, this introduced a small performance issue: the inner async
function expression was passed inline to the cache wrapper. While
`React.cache` memoizes the outer function, each unique set of arguments
would cause a new inner function object to be allocated.

Now we're generating (simplified):

```js
const $$RSC_SERVER_CACHE_0_INNER = async function getCachedData(id) {
  return fetch(`/api/data/${id}`);
};

export var $$RSC_SERVER_CACHE_0 = React.cache(function getCachedData() {
  return cache("default", "0815", 0, $$RSC_SERVER_CACHE_0_INNER, arguments);
});
```

The cache implementation is now hoisted to module scope with an `_INNER`
suffix as a const declaration with a named function expression. The
function name is preserved to ensure proper stack traces in dev. This
eliminates the repeated function allocations while preserving the
improvements from #85519.
2025-11-10 13:09:59 +01:00
Hendrik Liebau b07fb8644f Ensure user-space stack frame for 'use cache' in page/layout component (#85519) 2025-10-30 20:38:45 +01:00
Niklas Mischkulnig 3f09e569dc Turbopack: don't fail on export type in use server (#85054)
Allow `export type ... from "...";`
2025-10-21 19:54:37 +02:00
Zack Tanner da024c190a [cache components] move experimental.cacheHandlers out of experimental (#85157)
Moves this flag out of experimental so that custom `use cache` handlers
can be configured alongside the cache components release.
2025-10-21 10:41:28 -07:00
Zack Tanner 85c3d20a91 [cache components]: move flag out of experimental (#85035)
This moves `experimental.cacheComponents` to a top level config. As part
of this, I disabled some tests in `build-output-prerender` that assert
on `cacheComponents` appearing in the experimental list. In a separate
PR, I'm going to show that Cache Components is enabled next to the
bundler info.

This also updates some docs pages to remove "experimental" language.
2025-10-18 14:13:44 -07:00
Jiwon Choi 28b64e2f8d [Breaking] Remove deprecated unstable_rootParams (#84373)
This PR removed the deprecated `unstable_rootParams`. This feature was
not documented.
2025-10-01 18:49:49 +02:00
Jiwon Choi a432e06ded [Breaking] Remove deprecated built-in AMP (#84312)
This PR removes the deprecated built-in AMP support. Will follow up with
cleaning up the examples, docs, and codemods.
2025-09-30 18:54:26 +02:00
Hendrik Liebau 81bccc93e9 Guide users to experimental.cacheComponents config (#84121)
In error messages and in docs for `'use cache'` and related APIs, we now
guide users to the `experimental.cacheComponents` config instead of
`experimental.useCache`.

closes NAR-410
2025-09-23 12:23:59 +02:00
Hendrik Liebau 99b078b8da Emit build error when 'use cache' directive is misspelled (#83756)
Handles cases like:
- `'use cache:remote'` (missing space after colon)
- `'use cache : default'` (extra space before colon)
- `'use cache private'` (missing colon)
- `'use cache: '` (missing cache kind)

closes NAR-392
2025-09-13 20:59:39 +02:00
Remco Haszing 7aa5d16231 Use the automatic runtime for type checking (#83159)
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-09-02 12:35:42 +02:00
Luke Sandberg 2289975541 [turbopack] Adopt rcstr! more consistently (#80552)
Replace construction of `RcStr` instances on constant strings with the `rcstr!` macro which can shift construction costs to compile time and eliminate reference counting.

Performance impacts from all the dropped ref counts are minor but do exist

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/AwJ29EfoPcPdLSwCZxAz/e82b0e64-5803-4883-a89f-3090f1e937ce.png)

There is also a small progression in max heap which makes sense, laying out the static rcstrs should be a somewhat easier job compared to mimalloc.
2025-07-31 23:12:45 -07:00
Wyatt Johnson 8abbb3dc2e refactor: rename experimental.dynamicIO to experimental.cacheComponents (#81562)
## What?

Rename `experimental.dynamicIO` to `experimental.cacheComponents` across
the Next.js codebase.

## Why?

We're going to be merging the functionality of the `ppr`, `dynamicIO`
and `useCache` experimental flags into the singular `cacheComponents`
flag to reduce complexity of the codebase and simplify adoption for
users wanting to experiment with experimental features.

## How?

- Renamed the configuration option from `experimental.dynamicIO` to
`experimental.cacheComponents`
- Added deprecation handling with automatic migration for the old option
name
- Updated all documentation, tests, and internal references
- Updated Rust code in SWC transforms and Turbopack
- Maintained backward compatibility with deprecation warnings

NAR-158
2025-07-17 19:30:28 -06:00