Follow-up to https://github.com/vercel/next.js/pull/72631 this ensures
we properly update the `requestStore` when we detect pure IO case and no
dynamic methods are used like `cookies()` or `headers()` e.g. just a
fetch with no caching opts enabled.
---------
Co-authored-by: Zack Tanner <[email protected]>
This ensures we don't incorrectly update the static indicator status
during the dev warmup render which was causing it to show unexpectedly
with dynamicIO enabled.
Adds a `compiler.define` option to next.config.js to statically replace
any variables during build-time for Turbopack. This is similar to
Webpack's `DefinePlugin`.
Relates to: https://github.com/vercel/next.js/discussions/71476
---------
Co-authored-by: Tim Neutkens <[email protected]>
Using the information byte in a server reference ID, as introduced in
#71463, we can omit unused arguments when calling a `"use cache"`
function. This enables us, for example, to use a cached function in
conjunction with `useActionState` when the function does not need the
previous state, as shown below:
```ts
'use cache'
export async function getCachedRandomValue() {
return Math.random()
}
```
```tsx
'use client'
import { useActionState } from 'react'
import { getCachedRandomValue } from './cached'
export default function Page() {
const [result, formAction] = useActionState(getCachedRandomValue, null)
return (
<form action={formAction}>
<p>{result}</p>
<button>Submit</button>
</form>
)
}
```
Previously, in this use case, a new value would have been rendered for
every click. This is because React passes the previous state and the
form data as arguments into the action function. These two arguments are
then included in the cache key, resulting in a new cache key being
generated for every invocation.
_Note: This optimization is currently based purely on the function
signature. It does not yet detect when a param is declared, but not used
in the function body. It's also not yet applied for server actions._
### Why?
To customize Image Optimation, the user can use a custom loader, but
that information was out from the related lint error message.
Closes NDX-181
A multi-zone Next.js app might have complex rewrites for its client
assets. For these apps, resolving a source map through the
`/__nextjs_source-map` dev middleware might fail because the asset might
belong to a different app.
Instead of trying to resolve those rewrites (i.e. using `fetch` instead
of `fs`), we can just bypass the source map dev middleware for client
chunks. Because we control how those source maps are generated, we can
safely assume that the `sourceMappingURL` is relative to the filename,
with an added `.map` extension. The browser can just request this file,
and it gets served through the normal dev server, without the need to
route this through the source map dev middleware.
reverts #72258
This adds `expireTag()` and `expirePath` APIs which are replacing
`revalidateTag` and `revalidatePath`. As such this also marks
`revalidatePath` and `revalidateTag` as deprecated and marked for
removal.
The arguments passed to these methods match `revalidateTag` and
`revalidatePath` with the exception that `expireTag` can receive
multiple tags now as separate arguments which matches our new
`unstable_cacheTag()` API.
We are wanting to update these APIs as `revalidateTag` naming has caused
some confusion as to when the affected items will be updated. The
underlying behavior of `expireTag` is to mark an entry as out of date
and for it to no longer be used so we are expiring it.
If you call `expirePath('/blog/first'`) the next time that item is
requested it is considered expired so the cache will not be used for it
and a fresh entry will be generated. Similarly for `expireTag('posts',
'blog')` the next time any cache with that tag is requested it's
respective cache will not be leveraged and new cache will be populated.
---------
Co-authored-by: Zack Tanner <[email protected]>
Co-authored-by: Delba de Oliveira <[email protected]>
This pull request includes several changes to improve cache control
handling and add new test cases for verifying cache headers in the
standalone mode of the application.
Improvements to cache control handling:
*
[`packages/next/src/server/base-server.ts`](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aL3295-R3298):
Updated cache control conditions to check for `undefined` explicitly
before setting cache headers.
[[1]](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aL3295-R3298)
[[2]](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aL3318-R3324)
[[3]](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aR3354-R3365)
New test cases:
*
[`test/production/standalone-mode/required-server-files/required-server-files-app.test.ts`](diffhunk://#diff-0d083b6c7bd3a8a3e9c5ee854123ada3b72db58220d8b65912b047b082f834a2R104-R129):
Added test cases to verify that the correct cache headers are sent for
app routes and app pages.
New static and dynamic route handlers:
*
`test/production/standalone-mode/required-server-files/app/api/test/[slug]/route.js`:
Added a new dynamic route handler with forced static generation.
([test/production/standalone-mode/required-server-files/app/api/test/[slug]/route.jsR1-R7](diffhunk://#diff-1cf8a2cfdbb6473656b2456af0267556270fbbaa7ee2c37e2f3e6c6fed1e4d21R1-R7))
*
`test/production/standalone-mode/required-server-files/app/test/[slug]/page.jsx`:
Added a new static page with a revalidation interval and a function to
generate static parameters.
([test/production/standalone-mode/required-server-files/app/test/[slug]/page.jsxR1-R9](diffhunk://#diff-32038443ca3e4f28db37a6543966397682c64cf6f34e6dd03fd8096414d23022R1-R9))
- Fixes https://github.com/vercel/next.js/issues/65814
Co-authored-by: Janka Uryga <[email protected]>
Co-authored-by: Sam Ko <[email protected]>
If a user creates a custom fetch implementation in module scope, the
logic to preload entries during `next start` will result in fetch not
being patched before the userland implementation. As a result, it won't
opt into any caching heuristics from our patched fetch.
Fixes#71881 (in addition to the other PR in this stack)
If an ESM module only includes a `'use client'` directive and no
exports, which is the case for one of the modules that are included in
`@chakra-ui/system` for example, we must not try to add
`registerClientReference` statements for this module. This is a
regression from #71968.
fixes#72358closes#72359
`force-dynamic` will automatically disable caching on a fetch. If `force-dynamic` is set, and there's a `revalidate` value on the fetch, the revalidate value will be a no-op unless you explicitly opt into caching via `cache: 'force-cache'`. This changes the behavior to favor a positive revalidate value over `force-dynamic` when deciding to cache the fetch.
When using `fetch('', { cache: 'force-cache', { next: { revalidate: 5 } })` on a page that bailed out of ISR, we were effectively ignoring both values and treating the fetch as uncacheable, for several reasons:
- When `cache` and `revalidate` are both specified, we were assuming any combination of the two values is invalid, and we'd unset both the revalidate & fetch configs. In actuality these two properties are only problematic when they convey different caching semantics. This check was modified to instead only warn & unset on conflicting values, specifically `cache: 'no-store` and `revalidate: >0` as well as `cache: 'force-cache'` and `revalidate: 0`.
- When `force-dynamic` was set, we'd opt into no-store behavior on the fetch even if the fetch had an explicit cache config, which is incorrect.
Fixes#71881
### Why?
To unpin the TS version for testing added at #69889.
Closes NDX-287
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <[email protected]>
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the PR.
- Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide
### Adding or Updating Examples
- The "examples guidelines" are followed from our contributing doc https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to understand the PR)
- When linking to a Slack thread, you might want to share details of the conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
As the new chaining mechanism has been live for several weeks now, we're deprecating the old pathname based approach in favor of the new headers based approach. Pages that need to resume now will require the `Next-Resume: 1` header instead of having to call the `/_next/postponed/resume/<route>` route.
Based on:
- #72341
---
Creates an access token that the client passes when requesting a
segment. The token is sent to the client as part of the parent layout's
data.
The token is hash of the parent segment path and the parallel route key.
A subtle detail here is that it does *not* include the value of the
segment itself — a shared layout must produce the same access tokens for
its children regardless of their segment values, so that the client only
has to fetch the layout once.
Because this only affects prefetches, this doesn't need to be secure.
It's just for obfuscation. But eventually we will use this technique
when performing dynamic navigations, to support auth checks in a layout
that conditionally renders its slots. At that point we'll need to add a
salt.
In the new design for prefetching, instead of prefetching all the data
for a page in a single request, the client issues a separate request for
each segment. The benefit of using separate requests is that the
responses can be separately cached. For example, when prefetching
multiple pages that share the same layout, the layout data only needs to
be fetched once. Simlarly, when revalidating a tag, only segments that
access that tag need to be refetched.
The client needs to know about the structure of the route tree in order
to determine which segments can be reused. So, before it prefetches any
actual segment data for a page, it will first fetch information about
the route tree. The route tree contains the necessary data for sending
and caching prefetch requests.
This PR updates the server to respond to route tree prefetches. To
prefetch the route tree, the client sets the
`Next-Router-Segment-Prefetch` to `/_tree`.
At build time we merge dynamic params (e.g. `[lang]`) with search params
into the same object used as part of the pages/app renders. This is
semantically incorrect and has led to some unexpected downstream
behavior (such as dynamic params showing up as cache keys in flight data
for app router). Pages router seems to rely on this behavior (for ex,
`useRouter().query` combines both dynamic params with search params).
This avoids mutating `query` and instead combines them specifically in
the pages export case. This also fixes an inconsistency in where we're
reading params in pages render, specifically `getStaticProps` now reads
params from `params` rather than `query` to align with
`getServerSideProps` and not rely on the fact that we happen to merge
them.
In order to take advantage of the existing plumbing of the postponed state, we're injecting the resume data cache into the postponed state itself, as the data is always co-located. This ensures that stale resumes can utilize the data out of the box without any additional infrastructure configuration.
This adds a new ResumeDataCache concept to Next.js. This cache is persisted during production, and used for pre-seeding during development. Every route will generate its own resume data cache that will be used when partial prerendering is enabled. This lets us fill the caches during the prerender, and re-use those cache entries every time the page is resumed. This allows a future where we can reuse stale static shells while also reusing the resume data cache.
Pre-PPR on client navigations, we are currently determining whether or
not to render the underlying React components based on the presence (or
lack thereof) of `loading.js`. We'll render components up to the first
segment containing `loading.js`, and then stop at that level.
Similarly, if there's no `loading.js` in the tree at all, we'll return a
mostly empty prefetch. The underlying reason for this is that we cannot
assume a particular tree/subtree doesn't contain expensive invocations:
`loading.js` is a signal we use to detect where some sort of dynamic
call will happen. This heuristic is largely improved with PPR + DIO but
we still need to support this case.
Currently there's a bug that will lead to overfetching. When determining
if we should skip the component tree, we check the presence of loading
at that level, as well as the entire tree. This means that during
partial navigations when the server starts rendering deeper within the
tree rather than starting from the root, the presence of `loading.js` in
an earlier segment would incorrectly tell the router it should render
the page.
This updates the handling to check for a loading segment only within the
partial tree that's being diffed. That way when we recursively call
this, it won't look at earlier segments when deciding if there's a
loading segment deeper in the tree.
This PR also adjusts the server-patch reducer to be more resilient to
mismatching trees. Previously we triggered a hard navigation but this
actually can become a fairly common case if the RSC response doesn't
return initial bytes quickly enough, such as in `dynamicIO` when we're
warming the dev caches prior to a navigation. Instead we'll return the
state in-place and effectively discard the patch because the assumption
is the tree was patched elsewhere.
We will wait the server to respond with a compile success message after
a file is patched before proceeding to the next steps in the test to
reduce flakiness.
By doing so, we uncovered a few tests that were passing accidentally due
to flakiness of `patchFile`, and fixed them in the PR.
Follow up to #71113.
This generates a prefetch response for route segments, so the client can
request them individually, and reuse shared layouts between separate
page prefetches.
Since this is exclusive to PPR, segment prefetches are always static and
do not reach the application layer. They are served directly from cache.
(This part was implemented in the previous PR.)
The prerendered segment data is generated (and revalidated)
simultaneously with the prerender of the entire page, to ensure
consistency between parent and child segments. Since we always rebuild
the whole page, we can save an extra render of each segment by reusing
the Flight response that was used to generate the initial HTML.
We do this by decoding the page data using a server-side Flight
consumer, picking out an individual segment's data, then re-encoding it
as its own Flight response. We have to do this once per segment — not
ideal, but for now it's the only way to make sure the side effects from
the original Flight stream (e.g. Float preloads) are transferred to the
per-segment streams.
This PR does not yet include any updates to the client router.
This PR updates the SIGTERM and SIGINT exit codes to 143 and 130
respectively. These updated codes are what other tooling, such as
Nx/Turborepo, expects when running commands that did not completely
successfully due to receiving SIGTERM and SIGINT.
For Nx, the SIGINT (e.g. `Ctrl+C`) causes a bad build cache. Both Nx and
Turborepo will have bad cache when SIGTERM is received, which can happen
in a CI environment if a job times out, runs out of memory, etc.
I have a [repo here](https://github.com/jaysoo/next-cli-signals) that
demonstrates the wrong behavior with Turborepo. By exiting with the
wrong code, it can result in bad cache in CI or Docker.
Closes: https://github.com/vercel/next.js/issues/62906
---------
Co-authored-by: Sam Ko <[email protected]>
Co-authored-by: Zack Tanner <[email protected]>