we have auditing that server files aren't included in client chunks but the new htmlescape usage in next/script is causing that validation to fail. This refactors the utility into lib/shared
In a previous PR https://github.com/vercel/next.js/pull/88183, we added
`images.maximumResponseBody` but in only applied to external images.
This PR ensures the same config also applies to internal images.
This allows specifying a different deployment id for static immutable assets
- [x] rename `getImmutableAssetToken` to `getAssetToken` (because it can be non-immutable as well)
- [x] disable for webpack
Closes PACK-6534
For https://github.com/nextjs/adapter-vercel/pull/25
Part of PACK-6802
```
FAIL Turbopack test/unit/image-optimizer/lru-disk-eviction.test.ts
LRU disk eviction
√ should evict oldest entries on initialization (133 ms)
√ should evict old entries when new entries are set (124 ms)
× should promote entries on get() to prevent eviction (8 ms)
√ should return the same LRU instance on subsequent calls (1 ms)
√ should deduplicate concurrent init calls (2 ms)
√ should handle empty cache directory (2 ms)
√ should handle non-existent cache directory (2 ms)
● LRU disk eviction › should promote entries on get() to prevent eviction
EPERM: operation not permitted, rmdir 'C:\Users\ADMINI~1\AppData\Local\Temp\next-lru-test-dOXRaF\y'
```
Previously
```jsx
import img from "./x.png";
// x is "/_next/static/media/test.abc123.png?dpl=foo"
<Image id="static-unoptimized" src={x} unoptimized />
```
would lead to `/_next/static/media/test.abc123.png?dpl=foo&dpl=foo`
#90420 adds some related tests for the legacy loader as well
This PR adds an LRU disk cache so that reads and writes from the Image
Optimization API will evict old entries based on the value of
`images.maximumDiskCacheSize` configuration.
The LRU ensures that cache reads bump the entry to the top so that they
don't get evicted - only the least recently used entries get evicted.
When `next start` is run, if there is an existing disk cache the we will
replay the files in order to populate the LRU and respect
`images.maximumDiskCacheSize` if it was changed.
If no configuration is provided, default to 50% available disk space.
## Summary
Use `Buffer.indexOf` when available in `uint8array-helpers.ts` for
faster byte sequence scanning. Falls back to the existing manual loop on
non-Node environments.
## Test plan
- [ ] `pnpm test-unit test/unit/stream-utils/uint8array-helpers.test.ts`
passes
`NextURL` intentionally canonicalizes loopback hosts (127.x.x.x, [::1],
localhost) to localhost so that internal URL handling is consistent
across equivalent local origins.
However, we were applying a regex replacement to the entire URL before
parsing, which unintentionally rewrote loopback strings inside query
parameter values, eg `?redirect_uri=http%3A%2F%2F127.0.0.1...`. This is
unexpected for anyone that is explicitly passing through different
loopback values.
This fixes it by first parsing the URL with `new URL()`, and then only
apply the replacement logic to `parsed.hostname` when it is a loopback
host. This leaves search unchanged.
Fixes NEXT-4864
Fixes#89620
Fix `findClosestQuality` returning `0` when the `quality` prop on
`<Image>` is set to a low value (e.g. `quality={1}`), which causes the
image optimization server to reject the request with a 400 error.
### Cause
The `reduce` call in `findClosestQuality` used `0` as its initial
accumulator. Since `0` is not a valid quality value (must be 1-100), it
would win the "closest" comparison for any `quality <= 37` with the
default `qualities: [75]` config. This produced `q=0` in the image URL,
which the server rejects.
### Fix Description
Changed the `reduce` initializer from `0` to `config.qualities[0]`. This
is safe because the early return above already handles the empty array
case, so `config.qualities[0]` is always defined when reached.
Added a unit test for `quality=1` with `qualities=[75]` to verify it
returns `75` instead of `0`.
---------
Co-authored-by: Steven <steven@ceriously.com>
Original [PR](https://github.com/vercel/next.js/pull/88012/) has a bug
that attempted to validate on environment variables. Edited function to
not run validations on environment variables, only on the user provided
deployment id.
<!-- 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 #
-->
---------
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: JJ Kasper <jj@jjsweb.site>
- Adds a `process.env.NEXT_DEPLOYMENT_ID` -> `globalThis.NEXT_DEPLOYMENT_ID` replacement
- On startup, `globalThis.NEXT_DEPLOYMENT_ID` is initialized to `process.env.NEXT_DEPLOYMENT_ID_COMPILE_TIME`
This prepares for https://github.com/vercel/next.js/pull/88761 to replace `process.env.NEXT_DEPLOYMENT_ID_COMPILE_TIME` with reading `<html data-dpl-id>` so that we can remove the env var inlining
However, all of this is only done for Turbopack, because we cannot forward `globalThis.NEXT_DEPLOYMENT_ID` to web workers with Webpack easily.
Based on our metrics, the P99.9 for a source image is 47 MB so we can
adjust the default setting to be much lower (by changing from from 300
MB to 50 MB) in favor of reducing memory.
Flagged behind `experimental.strictRouteTypes`
This fixes issues where cache profiles where not included or routes not validated if `.next` was excluded to squeeze out every bit of TypeScript performance.
It also fixes a redundant type-check since we have separate dev and prod dist folders. If you run `next dev` and (`next build` or `next typegen`), you'd type-check routes and links twice. Now `next-env.d.ts` only exists once where we decide which dist folder to type-check.
Going forward, new Next.js type-checking should be added to `next-env.d.ts`. That file is fully controlled by Next.js and churning it, does not churn users since it's not in version control.
`next-env.d.ts` will be moved into `.next` in a follow-up. Ideally independent of the dist folder i.e. independent of `next dev` vs `next build`.
Closes https://linear.app/vercel/issue/NXT-124/https://github.com/vercel/next.js/pull/87319 but flagged.
In a previous PR https://github.com/vercel/next.js/pull/73184 the `?dpl`
query string was added to local images from static imports but not to
images without the static import.
This was a subtle change based on malte's PR review comment here:
https://github.com/vercel/next.js/pull/73184#issuecomment-2499126751
However, I can't think of reason why we should differentiate these two
since they are both related to the current deployment (as opposed to
remote images which live outside the deployment).
Furthermore, this string matching is causing microfrontends to fail to
add the `?dpl` because they have a path prefix and thus fail skew
protection.
So this PR fixes both problems by loosening the string matching to look
for src images that start with `/`.
Note: new PR description written by @timneutkens
## What?
Improves the detection of Google Tag Manager vs Google Analytics.
As indicated by the author of this PR it was confusing that when you
have Google Tag Manager set up it gives you an error message saying
you're adding Google Analytics even though it's Tag Manager.
I've updated the PR to have a separate message for Google Tag Manager
and expanded the error message docs too.
It also mentioned `next/script` in a bunch of places even though the
error doc recommends `@next/third-parties`. I've updated all cases to
refer to `@next/third-parties` instead.
<details>
<summary>Previous PR description</summary>
Google has multiple products with similar names: the "Google Tag" and
"Google Tag Manager". Google Tag Manager uses `gtm.js` whereas the
"Google Tag" uses `gtag`. Google Analytics previously used
`analytics.js` (<2017) and is now delivered via the "Google Tag".
Google Tag: `www.googletagmanager.com/gtag/js`
Google Tag Manager: `www.googletagmanager.com/gtm.js`
The `next-script-for-ga.ts` rule's matching list
(`SUPPORTED_HTML_CONTENT_URLS`) includes `gtm.js` which means when a
developer adds Google Tag Manager to their NextJS website, they'll
receive the warning and be encouraged to swap from `gtm.js` to `gtag`. A
developer asleep at the wheel (...me) may think...
> I'm using Google Analytics via Google Tag Manager, and NextJS is
suggesting I swap `gtm.js` for `gtag` because it will improve
performance. `gtag` sounds like it is part of "Google Tag Manager" so I
am going to follow the instructions so that my website is faster.
However, `gtag` is **not** compatible with `gtm.js` (they're different
products with similar names and similar purposes) and so making this
change will cause very confusing Google Tag Manager behaviour. I am
suggesting that `gtm.js` is removed completely from the rule, because
anyone using `gtm.js` should not be following these instructions. A
separate rule could be added specifically for Google Tag Manager, that
does not refer to `gtag`.
</details>
---------
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
## Enable synchronous access to native bindings
## What?
This PR refactors the SWC bindings loading mechanism to support synchronous access to bindings after they've been loaded. It introduces new functions `installBindings()` and `getBindingsSync()` to properly manage the bindings lifecycle.
`installBindings` is called early by tools that rely on them.
There were of course a few complexities:
* webpack loaders need to defensively install bindings to support being run by webpack
* the hacky `loadNativeSync` method used by `transformSync` remains required due to the jest-transformer API (i didn't see a clear initialization location).
* the `experimental.useWasmBinary` configuration is broken by design
* if the config is `next.config.ts` when we load SWC to transpile it, but that requires the native bindings, so we might load native bindings even when you ask for wasm. I added a warning message for this case and the workaround is to use the node native transpilation support.
* this should probably be a command line flag if it is important
* we need to lazily load the `swc/index.ts` module since it transitively loads `react` which reads `NODE_ENV` and various next entrypoints might modify that.
## Why?
This makes it clearer that we are correctly applying the `useWasmBinary` option and can simplify some code paths that now don't need to be `async`. This will be important in a future PR where i move some parts of issue formatting into rust/wasm. Having those APIs be async will decrease their usability.
This PR is the initiative of deprecating the edge runtime. Proxy will
default to Node.js runtime, and will not allow runtime config. If the
users want to use the edge runtime, they should stay on the Middleware,
though we recommend starting the migration.
---------
Co-authored-by: devjiwonchoi <devjiwonchoi@gmail.com>
Co-authored-by: JJ Kasper <jj@jjsweb.site>
> [!WARNING]
> v16 will not support backwards compatibility of legacy config. The
users can either migrate to flat config via `@next/codemod
next-lint-to-eslint-cli` or stay at v15.
### Why?
`eslint-config-next` is the recommended way to use the ESLint
configuration for Next.js, but it hasn't correctly supported the Flat
config. This PR makes `eslint-config-next` a Flat config by default, and
the users can use it by:
```js
import coreWebVitals from "eslint-config-next/core-web-vitals";
import typescript from "eslint-config-next/typescript";
const eslintConfig = [
...coreWebVitals,
...typescript,
{ ignores: [/* ...ignores to override default ignores */] },
];
export default eslintConfig;
```
Double-checked the usage at
https://github.com/vercel/next.js/tree/ba0db6f1c0256ac7a2941abaadc41f8e47c654a6/examples/with-supabase
### How?
- Converted to Flat config format
- Removed `@rushstack/eslint-patch` hack for peerDeps
- Replaced `@typescript-eslint/` packages to `typescript-eslint`
- https://github.com/vercel/next.js/pull/84874#discussion_r2432032100
- Replaced `env` property with `languageOptions.globals`
- https://github.com/vercel/next.js/pull/84874#discussion_r2432061040
### Follow up
- Update Codemod
- Update CNA templates
- Update Docs https://github.com/vercel/next.js/pull/84781
ESLint plugin defaults to flat config, and we also dropped the built-in
lint check at https://github.com/vercel/next.js/pull/83136, so we can
sunset the deprecated ESLint v8 testing.
### What?
Adds build-time validation to require explicit `default.js` files for
all parallel route slots (except the implicit "children" slot). This
validation is implemented in both Webpack and Turbopack bundlers.
### Why?
Parallel routes without `default.js` files currently cause silent 404
errors when users navigate to those routes. This creates confusion and
hard-to-debug issues because the routes appear to be configured
correctly but fail at runtime without any indication of what went wrong.
By making this validation explicit at build time, developers get
immediate feedback about missing required files with clear error
messages and documentation links, catching configuration mistakes before
deployment.
### How?
**Rust/Turbopack** (`crates/next-core/src/app_structure.rs`): Added
`MissingDefaultParallelRouteIssue` that emits a build error when a
parallel route slot is missing its `default.js` file. The validation is
skipped for the "children" slot since it's implicit and doesn't require
a default file.
**Webpack**
(`packages/next/src/build/webpack/loaders/next-app-loader/index.ts`):
Added validation that throws `MissingDefaultParallelRouteError` when
`default.js` cannot be resolved. The "children" slot falls back to the
existing `PARALLEL_ROUTE_DEFAULT_PATH` behavior for backward
compatibility.
**Error Class**
(`packages/next/src/shared/lib/errors/missing-default-parallel-route-error.ts`):
New error type with helpful messaging that includes the slot path,
explanation of the requirement, and a link to documentation.
**Migration Path**: Users who want the previous 404 behavior can
explicitly create a `default.js` that calls `notFound()`, or return
`null` for empty slots:
```tsx
import { notFound } from 'next/navigation'
export default function Default() {
notFound()
}
```
Users can also run the following Deno script to generate the default
files for them:
https://gist.github.com/wyattjoh/ba7263ecb637ef399d3e3e4db63ffbd6
**Breaking Change**: This is a breaking change timed for Next.js 16
beta. Builds will now fail if parallel route slots are missing required
`default.js` files.
This PR modifies Image behavior to require `images.localPatterns.search`
value when used with search queries in the `src` property:
```jsx
// Error
<Image src="/api/user?id=1" width="50" height="50" />
```
```ts
// next.config.ts
export default {
images: {
localPatterns: [
{
pathname: '/api/user',
// Either set explicit query string or leave undefined to match all
search: '?v=2',
},
],
},
}
```
It is to prevent malicious actors like Denial of Wallet (DoW) attacks
and strictly match the search queries for image optimization.
The deprecation warning was added at
https://github.com/vercel/next.js/pull/82627
---------
Co-authored-by: Steven <steven@ceriously.com>
We took a look at unique Next.js projects that have one or more requests
for a specific image size and here are the findings as seen from the
Image Optimization API:
- `w=16` 4.2%
- `w=32` 17.1%
- `w=48` 21.4%
- `w=64` 22.6%
- `w=96` 25.8%
- `w=128` 29.5%
- `w=256` 46.5%
- `w=384` 35.1%
- `w=640` 57.2%
Only 4.2% of Next.js projects ever made a request to a 16px width image.
This is low enough to remove from the default configuration so that all
other projects can benefit from reduced html
[srcset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset)
and fewer variations exposed from the backend API.
You might think that this means few developers are using `<Image
width={16} />` but it probably means that most displays nowadays use
devicePixelRatio 2 meaning that specifying a 16px image width will
actually fetch the 32px width to ensure it won't looking blurry on your
retina display.
BREAKING CHANGE: this is technically a breaking change but it won't
cause apps to stop working, its just 4% of them may have some requests
serve a 32px image instead of 16px. Those apps can of course opt in by
changing their `images.imageSizes` config back to allowing 16.
### Why?
This PR cleans up the incremental rollout of enabling `isolatedDevBuild`
throughout the CI, as it required many test changes (x-ref:
https://github.com/vercel/next.js/pull/84043).
- https://github.com/vercel/next.js/pull/84556
- https://github.com/vercel/next.js/pull/84558
- https://github.com/vercel/next.js/pull/84559
- https://github.com/vercel/next.js/pull/84562
This PR enables `experimental.isolatedDevBuild` by default so that users
can run `next dev` and `next build` in the same directory, and they
would not conflict. This occasionally happens when developing with AI
tools, where you have a running dev server, but the Agent runs `next
build`.
### How?
- Removed `__NEXT_EXPERIMENTAL_ISOLATED_DEV_BUILD` flag and its usage
from CI and tests
- Updated tests that were not caught via rollout (e.g., missed out on
test-*-windows)
- Moved `isolatedDevBuild` option out of experimental
- Added Telemetry
Will follow up with docs.
**Update:** This also fixes a bug pointed out by Graphite where the deletion function could hang forever because the `t` variable used for tracking attempts wasn't properly incremented.
---
https://vercel.slack.com/archives/C04KC8A53T7/p1759360239193629
This is a critical path for `next dev` and `next build` initialization.
On Windows, it's quite common to get an error while trying to recursively delete directories for one of two reasons:
**Temporarily open files:**
1. You open the directory.
2. The user's AV detects the directory as opened and quickly scans the files in that directory.
3. You try to delete a file, but on Windows, files cannot be deleted when open.
**Deletion is not instant/atomic:** It can take some time after deleting files for the directory to become empty.
For this reason, we perform two retries with a 100ms delay after the first attempt and a 200ms delay after the second attempt.
* Node does not use retries by default, but has an option to do so with a `100ms * attemptNumber` (linear backoff) delay, similar to what we do: https://github.com/nodejs/node/blob/b5638e1765d3d1241d07457e767f27e3ee6b9dd2/lib/internal/fs/utils.js#L774-L779
* Node used to use 3 retries by default, but that was changed in v14: https://github.com/nodejs/node/commit/7e85f068a48b284a253abcb5eb3173320869b8fe
* Rust tries to delete 64 times in a loop without sleeping, but with a call to `thread::yield_now`: https://github.com/rust-lang/rust/blob/4da69dfff1929cc79872b3d05ab7112d84753dba/library/std/src/sys/fs/windows/remove_dir_all.rs#L154-L171
In the vein of reducing time spent sleeping in the critical initialization path (@timneutkens), I think we should be more aggressive, I'm thinking using a 10ms delay (arbitrary number), but with an exponential backoff, so that we still retry over the same 300ms period as we currently do? Thoughts?
The difficulty is that this is on Windows, so it's hard for me to get good numbers about what impact this would have (if any).
## Context: What's broken?
For using `styled-jsx` with `react-compiler`, we need to use `babel-loader`, but it turns out that outside of our current narrow use of `react-compiler`, our usage of `babel-loader` in Turbopack is totally broken:
* Babel configs cause us to exit with an error claiming it's not supported.
* We have code in Turbopack for enabling `babel-loader`, but we try to use the version from NPM instead of the one bundled internally with Next.js. We should use the one bundled internally with Next.js.
* We shouldn't run all the babel transforms in the `next/babel` preset because they're redundant with SWC. `react-compiler` added a "standalone" mode to the babel-loader that's close to what we want, but I need to extend it for Turbopack's use-case.
## This PR
- Remove the warnings/errors that say babel isn't supported with Turbopack.
- Automatically enable babel when a config file is present.
- Modify the `next/babel` preset in Turbopack (I'm re-using/extending `'standalone'` mode) to enable syntax plugins, but disable any transformations or down-leveling (we expect SWC to do this). This is a bit hacky because babel's presets aren't designed to support this configuration.
- Pre-bundle `plugin-syntax-typescript`. This is a stub package that's also used by the typescript preset, so this really just exposes an extra entrypoint into the babel bundle.
- Migrate one of the legacy babel `test/integration` tests (that uses flow syntax) to `test/e2e`. The turbopack `foreign` condition doesn't work correctly without test isolation.
- Enable Turbopack for all the babel-related integration and e2e tests I could find.
## Follow-ups
- [ ] https://github.com/vercel/next.js/pull/83502 React compiler can cause babel to run *twice*. Merge the logic for automatic configuration of `react-compiler` (currently in JS) and `babel` (in Rust), so that this can't happen.
- [ ] https://github.com/vercel/next.js/pull/84002 Update the docs to show that Babel is now supported.
> [!NOTE]
> This is not a breaking change for `eslint-config-next` as they are
modified to use the legacy. Therefore, CNA templates or current users
that use `eslint-config-next` won't be affected.
### Why?
This PR uses v16 as an opportunity to make the Flat config the default
for `@next/eslint-plugin-next`. Since ESLint v10 will drop the Legacy
config, it is recommended for the plugins to migrate the default config
to Flat. This follows the recommended [plugin migration guide to flat
config](https://eslint.org/docs/latest/extend/plugin-migration-flat-config)
from ESLint.
Along with the migration, it uses the types from ESLint to let users
have correct type safety when using the plugin.
Fixes https://github.com/vercel/next.js/issues/81695
Fixes https://github.com/vercel/next.js/issues/81083
Fixes https://github.com/vercel/next.js/issues/82967
Closes NEXT-4663
The Image component's existing `priority` prop is confusing since its
not obvious what it does.
In order to improve clarity, we are introducing a `preload` prop and
deprecating the `priority` prop.
We also updated the dev warning to no longer suggest using this prop for
the LCP and instead use `loading="eager"`.
## Background
We have default allowlists for the `url` (localPatterns/remotePatterns
config) and `w` (imageSizes/deviceSizes config) but we don't have a
default allowlist for `q` (currently opt-in with via qualities config).
## What's changing?
BREAKING CHANGE: This PR is a breaking change that sets the default
allowlist to `qualities: [75]`, meaning that anything other than 75 is
invalid. Since most images don't set the quality prop and therefore
default to 75, most apps will be unaffected.
However, we can be even more gracious when users upgrade because we can
coerce the value automatically to 75 (or rather any value in `qualities`
allowlist). In dev, this will print a warning explaining why the prop
was not observed. This also works if you had `qualities` configured but
removed 75, since the closet matching value in the array will be used
instead.