🔄 Sync from upstream - 2026-01-12#240
Merged
lakshit-hivel merged 42 commits intocanaryfrom Jan 12, 2026
Merged
Conversation
…d process (vercel#88230) ## Eliminate duplicate `loadConfig` calls during development server startup ### What? Remove duplicate `loadConfig` calls from the parent process (`next-dev.ts`) by passing `distDir` via IPC from the child process where config is already loaded. ### Why? Previously, when booting the development server: 1. The **child process** (`start-server.ts` → `router-server.ts`) would call `loadConfig` to get the full configuration for the actual server 2. The **parent process** (`next-dev.ts`) would also call `loadConfig` separately just to access `config.distDir` for telemetry and trace uploads Since these are separate processes, the in-memory config cache couldn't be shared, resulting in redundant config loading work. ### How? Extended the existing IPC messaging to include `distDir` when the child process sends `nextServerReady`: ``` Parent (next-dev.ts) Child (start-server.ts → router-server.ts) | | |-------- fork() ------------------>| |<------- nextWorkerReady ----------| |-------- nextWorkerOptions ------->| | | loadConfig() ← only called here now |<-- nextServerReady + distDir -----| | | Store distDir for telemetry/trace uploads ``` **Changes:** - **`render-server.ts`**: Added `distDir` to `ServerInitResult` type - **`router-server.ts`**: Return `config.distDir` in `initialize()` result and pass to render server opts - **`start-server.ts`**: Return `distDir` from `startServer()` and include it in IPC message - **`next-dev.ts`**: Receive `distDir` from IPC, remove both `loadConfig` calls, use `distDir` directly for telemetry/trace
…ge (vercel#88247) This updates to expand our normalized interface of handler(req, ctx) to edge runtime as well and middleware. This also applies some fixes for outputs and routes for app router. Validated against our test suite here vercel/vercel#14102 to start. Once nextjs/adapter-vercel#6 is landed we can start wiring up the full E2E test suite for validating.
## Move "Ready in X" log before config loading and eliminate duplicate `loadConfig` calls ### What? Reorder the dev server startup flow so the "Ready in X" log appears before loading the user's `next.config.js`, and eliminate duplicate `loadConfig` calls in both dev and build paths. ### Why? Previously, the "Ready in X" time included the time spent loading and evaluating the user's `next.config.js` file. This made the framework appear slower than it actually is, especially for projects with complex config files or slow config evaluation. Additionally, config was being loaded twice: - **Dev server**: Once in `getStartServerInfo()` just for logging, then again in `getRequestHandlers()` - **Build**: Once for the main build, then again in `getStartServerInfo()` just for logging ### How? **Before:** ``` 1. getStartServerInfo() → loadConfig #1 (slow - blocks on next.config.js) 2. logStartInfo() → logs version, URLs, experimental features 3. "Ready in X" ← time includes config loading 4. getRequestHandlers() → loadConfig #2 ``` **After:** ``` 1. logStartInfo() → logs version, URLs, envInfo (no config needed) 2. "Ready in X" ← reflects actual framework startup time 3. getRequestHandlers() → loadConfig (once) 4. logExperimentalInfo() → logs experimental features ``` **Changes:** - Split `logStartInfo` into two functions: - `logStartInfo()` - basic info (version, URLs, env) - no config needed - `logExperimentalInfo()` - experimental features and cacheComponents - Removed `getStartServerInfo()` which was loading config unnecessarily - Added `experimentalFeatures` and `cacheComponents` to `ServerInitResult` so they can be passed back after config loads - In build, added `reportExperimentalFeatures` callback to the existing `loadConfig` call instead of loading config twice --------- Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
When self-hosting Next.js, it's possible to customize a cache handler for ISR. Self-hosted Next.js also makes use of a similar cache interface for `next/image`, but there's no way to customize this cache handler. This plugs into the [existing ability](https://nextjs.org/docs/app/api-reference/config/next-config-js/incrementalCacheHandlerPath) to customize a `cacheHandler` to support the `IMAGE` type. This lets you implement whatever constraints you might have on your self-hosted environment, eg the need for an LRU cache, or storing optimized images outside of disk. This is currently opt-in because it's a breaking change for cache handlers to start receiving `IMAGE` cache types, which we'll make default in the next major.
Closes PACK-5850 Closes vercel#86132 Closes vercel#86714 The problem was that you get this with scope hoisting: ```js "index.js": () => { // foo.js // exports object read here const self_import = turbopack_import("foo.js") // exports object created here __turbopack_esm__([...], "foo.js") // index.js .... } ``` without scope hoisting, that exports object is already initialized before the module factory runs ```js "foo.js": () => { // exports initialized here const self_import = turbopack_import("foo.js") __turbopack_esm__([....]); } .... ``` so let's fix it by making it hoist the `__turbopack_esm__` statement (just as we did before always) in the case of self-imports --- This bug is actually very similar to vercel#82827. It also executes `data.js` twice. The problem is that if a module imports itself, ```js "[project]/input/data.js [test] (ecmascript)", ((__turbopack_context__) => { "use strict"; var __TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__$3c$locals$3e$__ = __turbopack_context__.i("[project]/input/data.js [test] (ecmascript) <locals>"); var __TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/input/data.js [test] (ecmascript)"); __turbopack_context__.s([ "Data", 0, __TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__, "bar", ()=>__TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__$3c$locals$3e$__["bar"], "foo", ()=>__TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__$3c$locals$3e$__["foo"] ]); }), ``` and with scope hoisting, the `import("id")` happens before the `esm_export(..., "id")`: ```js module.exports = [ "[project]/index.js [test] (ecmascript)", ((__turbopack_context__) => { "use strict"; // MERGED MODULE: [project]/index.js [test] (ecmascript) ; // MERGED MODULE: [project]/data.js [test] (ecmascript) <locals> ; function foo() { return 'foo'; } function bar() { return 'bar'; } ; __turbopack_context__.s([ "bar", ()=>bar, "foo", ()=>foo ], "[project]/data.js [test] (ecmascript) <locals>"); // MERGED MODULE: [project]/data.js [test] (ecmascript) <export * as Data> ; // MERGED MODULE: [project]/data.js [test] (ecmascript) ; var __TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__$3c$locals$3e$__ = __turbopack_context__.i("[project]/data.js [test] (ecmascript) <locals>"); var __TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/data.js [test] (ecmascript)"); __turbopack_context__.s([ "Data", 0, __TURBOPACK__imported__module__$5b$project$2f$input$2f$data$2e$js__$5b$test$5d$__$28$ecmascript$29$__, "bar", ()=>bar, "foo", ()=>foo ], "[project]/data.js [test] (ecmascript)"); ```
https://doc.rust-lang.org/reference/attributes/derive.html#r-attributes.derive.automatically_derived We discussed this during our morning team meeting. I had an LLM write this. This does not identify any new dead code.
This auto-generated PR updates the development integration test manifest used when testing Rspack.
…ercel#87993) ### What? Adds a Claude Code plugin marketplace to the Next.js repository with an initial `cache-components` plugin that provides expert guidance for Cache Components and Partial Prerendering (PPR). ### Why? Cache Components introduces a new programming model that combines Partial Prerendering, Dynamic I/O, and the `"use cache"` directive. Team members and contributors need guidance on: - The `'use cache'` directive and its variants (`private`, `remote`) - Cache lifetime configuration with `cacheLife()` and predefined profiles - Cache tagging and invalidation with `cacheTag()`, `updateTag()`, `revalidateTag()` - Parameter permutation rendering and subshell generation with `generateStaticParams` - Migration from deprecated `revalidate` and `dynamic` segment configs - Build-time error resolution (dynamic data outside Suspense, uncached data, etc.) A Claude Code plugin allows this knowledge to be distributed directly from the repo and proactively activated when working in projects with `cacheComponents: true`. ### How? Introduces the `.claude-plugin/` directory structure: ``` .claude-plugin/ ├── marketplace.json ← Marketplace catalog (name: "nextjs") └── plugins/ ├── README.md ← Documentation for adding plugins └── cache-components/ ├── .claude-plugin/plugin.json ← Plugin manifest ├── README.md ← Plugin documentation └── skills/cache-components/ ├── SKILL.md ← Core concepts, mental model (496 lines) ├── REFERENCE.md ← API reference, migrations (875 lines) ├── PATTERNS.md ← 12 production patterns (781 lines) └── TROUBLESHOOTING.md ← Build errors, debugging (721 lines) ``` **Installation:** ```bash /plugin marketplace add vercel/next.js /plugin install cache-components@nextjs ``` **Key skill features:** - **Proactive activation** when `cacheComponents: true` is detected in next.config - **Mental model decision tree** for thinking through caching decisions - **Cache scope clarification** explaining what creates new cache entries - **updateTag vs revalidateTag guide** with decision table and examples - **Migration scenarios** from deprecated `revalidate`/`dynamic` segment configs - **Quick debugging checklist** for common cache issues - **Parameter permutation rendering** (how `generateStaticParams` creates subshells) - **12 production patterns** including e-commerce, multi-tenant SaaS, and subshell composition ### Documentation Highlights | Section | Description | |---------|-------------| | Mental Model | Decision tree for when to use `'use cache'`, `'use cache: private'`, or `<Suspense>` | | Cache Scope | What creates new cache entries (function identity, arguments, file path) | | updateTag vs revalidateTag | Decision guide with e-commerce examples | | Migration Scenarios | Before/after examples for `revalidate`, `force-dynamic`, and ISR patterns | | Quick Debugging Checklist | Copy-paste checklists for common issues |
…ext::with_context` calls (vercel#88293) `anyhow!` works here because we just need something that implements `Display`, but `format!` is better.
…8243) ### What? Removes the `experimental.ppr` configuration flag and consolidates Partial Prerendering (PPR) functionality into the `cacheComponents` architecture. ### Why? Having two separate systems (PPR flag and cacheComponents) created dual code paths and complexity. PPR is now implicitly enabled when cacheComponents is enabled, simplifying the codebase. ### How? - Deleted `postpone.ts` and `ppr.ts` utility files - Removed `PrerenderStorePPR` work unit type and all PPR-specific work unit cases - Removed React.unstable_postpone-based dynamic rendering logic - Deprecated `experimental.ppr` config (kept for backwards compatibility) - Simplified build system to check only `cacheComponents` flag - Updated tests to remove PPR-specific behavior expectations This removes ~986 lines of code across 48 files.
<!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change(s) that you're making: ## For Contributors ### Improving Documentation - Run `pnpm prettier-fix` to fix formatting issues before opening the PR. - Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide ### Fixing a bug - Related issues linked using `fixes #number` - Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ### Adding a feature - Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas) - Related issues/discussions are linked using `fixes #number` - e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) - Documentation added - Telemetry added. In case of a feature if it's used or not. - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ## For Maintainers - Minimal description (aim for explaining to someone not on the team to understand the PR) - When linking to a Slack thread, you might want to share details of the conclusion - Link both the Linear (Fixes NEXT-xxx) and the GitHub issues - Add review comments if necessary to explain to the reviewer the logic behind a change ### What? ### Why? ### How? Closes NEXT- Fixes # -->
### What? fix the task category
## What? Explain in agent.md where the Next.js core code lives.
It didn't actually use `output: "standalone"` The list should be accurate now.
### What? This makes database read spans being grouped per family
This removes quite a lot of files. But some of them are simply needed because we load `build/swc/index.js`, e.g. the two following examples. Removing them would require some more refactoring. <img width="1274" height="680" alt="Bildschirmfoto 2026-01-09 um 14 22 07" src="https://github.com/user-attachments/assets/2354b9f2-1bfd-438d-af54-e69e8934cbc4" /> <img width="1346" height="474" alt="Bildschirmfoto 2026-01-09 um 14 23 15" src="https://github.com/user-attachments/assets/8f516cd6-321e-4f9c-bade-19eed7093c88" />
…ever (vercel#88190) This PR refactors the Resolution Plugin traits to add new `Always` or `Never` enum variants to `resolve condition`. This allow plugins (like [ExternalsPlugin](utooland/utoo#2494) when no externals are configured) to skip the expensive `matches()` task calls entirely. Testing on a medium project showed a reduction of ~1.4k `resolve_call` tasks. I think this can be shared to upstream for future improvement of `resolve plugin` See the metrics for improvements. <img width="1400" height="600" alt="image" src="https://github.com/user-attachments/assets/06eae96e-070a-43c3-9f68-a3a27ee7dc0d" /> --------- Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
Apply vercel#83800 without merge conflicts.
### What? children need to be prefetched too, since connect_child accesses the child to check for scheduling
### What? Add the point of stale detection to the trace
…fore erroring (vercel#88119) ### What? The graph traversal used to early exit when there are errors. This leads to cycles to continuously executing the graph traversal to discover more task one by one. This leads to bad incremental performance.
## Fix: Remove unnecessary decimal place in millisecond duration formatting ### What Fixed `durationToString` to display whole milliseconds (e.g., "193ms") instead of showing a redundant decimal place (e.g., "193.0ms"). ### Why The "Ready in X" message was displaying durations like "Ready in 193.0ms" which looks incorrect. The `.0` suffix provides no useful information and makes the output look like a bug. ### How Changed `.toFixed(1)` to `.toFixed(0)` for millisecond formatting in `durationToString()`. This aligns with the behavior of the newer `durationToStringWithNanoseconds()` function which already uses `.toFixed(0)` for milliseconds. **Before:** `✓ Ready in 193.0ms` **After:** `✓ Ready in 193ms`
…#86346) Before: ``` Module not found: Can't resolve 'next/dist/esm/build/templates/helpers' failed to analyze ecmascript module '[project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js [ssr] (ecmascript)' Caused by: - failed to parse [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js - Transforming and/or parsing of [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js failed - failed to deserialize `swc_common::plugin::diagnostics::PluginCorePkgDiagnostics` - Mismatch { name: "array", found: 48 } Debug info: - Execution of <ModuleAssetContext as AssetContext>::process_resolve_result failed - Execution of <ModuleAssetContext as AssetContext>::process failed - Execution of <EcmascriptModuleAsset as Module>::side_effects failed - Execution of analyze_ecmascript_module failed - failed to analyze ecmascript module '[project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js [ssr] (ecmascript)' - Execution of <EcmascriptModuleAsset as EcmascriptParsable>::failsafe_parse failed - Execution of parse failed - failed to parse [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js - Transforming and/or parsing of [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js failed - failed to deserialize `swc_common::plugin::diagnostics::PluginCorePkgDiagnostics` - Mismatch { name: "array", found: 48 } Import map: aliased to module 'next' with subpath '/dist/esm/build/templates/helpers' inside of [project]/ https://nextjs.org/docs/messages/module-not-found ``` After: ``` ./packages/next/document.js Failed to execute SWC plugin An unexpected error occurred when executing an SWC EcmaScript transform plugin. This might be due to a version mismatch between the plugin and Next.js. Failed to execute @swc/plugin-react-remove-properties Caused by: 0: failed to deserialize `swc_common::plugin::diagnostics::PluginCorePkgDiagnostics` 1: Mismatch { name: "array", found: 48 } ```
…7216) This was disabled for the 16.1 release. so re-enable it just to get rid of the slightly odd `!isStableBuild` pattern and also ensure i don't forget to ship it for 16.2
This auto-generated PR updates the development integration test manifest used when testing Rspack.
This auto-generated PR updates the production integration test manifest used when testing Rspack.
## What? Measures the time to `Ready in X ms` in the PR stats action so that improvements/regressions on it are highlighted on each PR. --------- Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
## What? Adds the docs-only change check to the `stats-aggregate` job. ## Why? The `stats` job already skips work for docs-only changes using `scripts/run-for-change.mjs`, but the `stats-aggregate` job was missing this check. This caused unnecessary job runs when PRs only contain documentation changes. ## How? - Added the "Check non-docs only change" step (same pattern as the `stats` job) - Added conditional `if` checks to all subsequent steps - Changed `fetch-depth` from 1 to 25 (required for the change detection script to check commit history)
When a parallel route does not match the current URL, in its place we render the render the last active route that matched that slot. When we next refresh the page, we track some additional state to inform the router how to refresh the old, "inactive" routes that aren't reachable from the outermost, "active" route. Before this PR, the only state we tracked was the URL of the page that last matched the inactive segment. After this PR, I am also tracking the search query string of the old route. This can't be inferred from the URL alone because the URL may have been rewritten by the server. We don't need the search query to perform a network request — that is handled by the URL alone — but we do need it in order to construct a cache key for the page segments. Today we read the cache key from the FlightRouterState, which has all the params embedded inside of it, but eventually I want to remove all uses of FlightRouterState that aren't about sending/receiving data from the server or storing the tree as state in the browser's history entry. So this is an incremental step towards that goal.
RouteTree is the client version of FlightRouterState. It's the same representation of the route tree, but it structured for optimized lookups of the client cache. The plan is the make this the primary/only type used for dealing with routes on the client; FlightRouterState will be used a transport format only.
Based on: - vercel#87203 - vercel#87256 --- Currently, there's a cliff when navigating to a route that is unknown to the client. The prefetch cache is bypassed completely because we don't know the structure of the target route, and therefore we don't know which segments we might be able to use to construct a loading state (or even a fully cached response). However, because RSC responses are streaming, we can take advantage of the fact that the first chunk of the response contains the route tree. So as soon as we receive the first chunk, we can show a cached loading state to the user (if available), even while we wait for the rest of the response to arrive from the server. To access a segment's cache, you need its corresponding RouteTree. Previously this was not available during an unprefetched navigation because those objects were only created during a prefetch. But now that we've migrated the navigation implementation to use RouteTrees, too, we can access the cache directly inside the main navigation function, rather than having to do two separate passes like before. In other words, the only difference between a navigation to an unknown route versus a prefetched route is the extra latency required to get those first bytes from the server. Once the route tree resolves, the rest of the implementation and behavior is identical.
Based on: - vercel#87203 - vercel#87256 - vercel#87293 --- Removes the `loading` as a separate field in the server response payload. Instead, it is passed as part of the component data (the `rsc` field). This simplifies much of the logic on the client because, logically, they were already coupled. Unifying the fields removes the possibility that they'll get out of sync due to some implementation mistake.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔄 Upstream Sync
This PR syncs the latest changes from the upstream repository.
Changes: 42 new commit(s) from upstream
Recent Upstream Commits:
This PR was automatically created by the multi-repo orchestrator.
Repository: next.js
Timestamp: 2026-01-12T13:24:08.468328