## 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>
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.
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.
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>
### 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 -->
`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.
## 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.
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
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.
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
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 '📙' }
```
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~~
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.
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
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.
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.
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.
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
## 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
When a server action or `'use cache'` function is defined as a
synchronous function, the error message now only marks the function name
for better clarity. Previously, the entire function body was marked,
which looks fine in small test fixtures, but is pretty messy for larger
functions, both in the terminal as well as in the dev error overlay.
For anonymous default exports we can't optimize this and are still
marking the entire function body, as we don't have a name to refer to.
closes NAR-165
When passing server actions or nested `'use cache'` functions inside of
cached components as props to client components, we need to make sure
that those are registered as server references, even when restoring the
parent component from the cache, e.g. during the resume of a partially
static shell. Otherwise, React would throw a runtime error while trying
to serialize the props.
<details>
<summary>Example</summary>
```tsx
import { connection } from 'next/server'
import { Suspense } from 'react'
export default function Page() {
return (
<div>
<Suspense fallback={<h1>Loading...</h1>}>
<Dynamic />
</Suspense>
<CachedForm />
</div>
)
}
const Dynamic = async () => {
await connection()
return <h1>Dynamic</h1>
}
async function CachedForm() {
'use cache'
return (
<form
action={async () => {
'use server'
console.log('Hello, World!')
}}
>
<button>Submit</button>
</form>
)
}
```
</details>
Previously, for inline server functions, the Next.js compiler placed the
`registerServerReference` calls where the server function was originally
declared. When the enclosing function was restored from a cache, this
call was skipped and the reference was not registered, leading to the
serialization error. To fix it, we can hoist the
`registerServerReference` call into the module scope, where the
reference itself also has been hoisted to. For simplicity, we're doing
this now generally, regardless of whether the server function is inline
or top-level.
Note: Since `registerServerReference` uses `Object.defineProperties` to
mutate the given reference, we don't need to assign the result to
anything. We already did this for exported functions of a module with a
top-level `'use server'` directive.
closes NAR-167
unstable_rootParams is a server component API and should not be allowed
to be accessed from client components. This change adds a compiler error
if this import is detected within the client module graph.
### What?
Remove magic comments for disabling export merging in the advanced tree shaking of turbopack.
### Why?
Turbopack magic comments for tree shaking + server actions are not required anymore since https://github.com/vercel/next.js/pull/76938.
This PR changes the server action generated code a bit to work around a
typescript bug and remove some false positives we got while
typechecking: https://github.com/microsoft/TypeScript/issues/61165
The trick is that typescript seems to look for *exactly*
`Object.defineProperty(obj, 'literal', { value: ... })`, and changing
any part of the expression bypasses the bug, so we can just use
`Object['defineProperty']` instead.
The `"use cache"` directive is not compatible with the Edge runtime.
When the `experimental.useCache` flag is enabled, we now emit a build
error for pages with `export const runtime = 'edge'`. This is analogous
to using the `experimental.dynamicIO` flag.
The other route segment configs that are forbidden when `dynamicIO` is
enabled, are currently still allowed for `useCache`:
- `dynamicParams`
- `dynamic`
- `fetchCache`
- `revalidate`
The issues with the current export statement validation for app router
pages are documented in the added fixtures, see also the inline comments
in the diff.
With this PR, we are allowing _static_ class methods to be annotated with `"use cache"` or `"use server"`.
Class _instance_ methods on the other hand are not allowed as server functions.
Accessing `this` or `arguments` in server functions is not allowed. With
this PR, we are now emitting build errors in this case.
---------
Co-authored-by: Janka Uryga <lolzatu2@gmail.com>
This PR has two main goals:
- **Consolidate the detection of server directives in modules and function bodies.** Previously, these were two separate implementations with significant overlap, but also some [questionable discrepancies](https://github.com/vercel/next.js/pull/72811#discussion_r1843660381).
- **Model the current directive (in a file or function) using an enum instead of two separate booleans.** This change prevents any confusion that both directives might be present simultaneously. Additionally, we're now emitting an error if multiple directives (`"use server"` and `"use cache"`) are defined in the same location (at the top of a file or function body).
A mixed usage of `"use server"` and `"use cache"` _across different locations_ is still allowed, e.g. `"use cache"` at the top of a file, and `"use server"` in a function.
> [!NOTE]
> The diff may be tricky to review because chunks from two different functions are combined into a single function. Fortunately, we have comprehensive test coverage for the transforms, which instills high confidence that these changes are correct.
### What?
Enable single-incoming-edge optimization for module fragments with `ModulePart::Export`.
### Why?
It will reduce the number of modules greatly.
### How?
Closes PACK-3481
By adding `visit_mut_function` we can deduplicate the code that's common between `visit_mut_fn_expr` and `visit_mut_fn_decl`. And more importantly, this prepares us for handling the transform of method props, which will also use `visit_mut_function`.
As a positive side effect this brings two small improvements with it:
- always highlight the whole function when `async` is missing, not only the identifier
- assign a function name to an anonymous arrow function expression in a variable declaration
When a `"use cache"` directive with a custom cache kind is used, e.g.
`"use cache: custom"`, a cache handler with the same name must be
specified in the Next.js config:
```js
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
experimental: {
dynamicIO: true,
cacheHandlers: {
custom: require.resolve('path/to/custom/cache/handler'),
},
},
}
module.exports = nextConfig
```
If this is not the case, we emit a build error with an error message
that explains this requirement.
<img width="795" alt="Screenshot 2024-11-14 at 23 30 01"
src="https://github.com/user-attachments/assets/bd138c97-608f-42ce-abb2-edb3e44edc3f">
When we'll get a docs page for this experimental config, we will add the
usual "Read more: ..." hint as well.
---------
Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
Co-authored-by: Janka Uryga <lolzatu2@gmail.com>
This improves maintainability and readability by decluttering the server actions transforms implementation, dedupes a few error messages, and consistently uses periods and trailing newlines for all error messages.
The same approach is already used for the React Server Components transforms.