fix(app-router): honor reactStrictMode#2679
Open
NathanDrake2406 wants to merge 2 commits into
Open
Conversation
App Router client roots were never wrapped in React StrictMode, so the router ignored both Next.js default-on behavior and explicit configuration. Publish the resolved App Router strict-mode define and select StrictMode or Fragment around the shared hydration and CSR root. This preserves the Pages Router default while matching Next.js for App Router applications. Add config and browser regression coverage for default, enabled, and disabled values.
commit: |
Contributor
Performance benchmarksCompared 0 improved · 0 regressed · 6 within ±1.5%
View detailed results and traces 🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head |
The App Router browser coverage only exercised the default-enabled path, so a boolean/string mismatch could enable Strict Mode even when the emitted define was false. Run an isolated development fixture with reactStrictMode set to false and assert a single client render. The fixture keeps its optimizer cache and server lifecycle separate from the default-enabled app.
NathanDrake2406
marked this pull request as ready for review
July 23, 2026 07:05
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.
Fixes #2676.
Summary
reactStrictModecontract__NEXT_STRICT_MODE_APPfrom resolved config and wrap the shared hydration/CSR root withStrictModeorFragmentsrc/index.ts,server/app-browser-entry.tsreactStrictMode: falseremains an opt-outWhy
Next.js enables Strict Mode by default for the App Router and preserves an explicit
reactStrictMode: false. vinext already preserved the resolvedboolean | nullvalue, but the App Router build did not publish that value to its browser entry and the browser root was never wrapped. As a result, the App Router ignored both the default and explicittrueconfiguration.This follows Next.js's implementation: resolve the App Router default in the build define, select
StrictModeorFragmentonce, and use that wrapper for both hydration and the CSR error fallback. I found no dedicated Next.js behavioral test for this config; the pinned build and client sources below are the executable contract.What changed
reactStrictMode: truereactStrictMode: falsevinext checkreactStrictModeas partialThe browser regressions count client renders without scheduling a React state update. The default fixture expects two development renders; an isolated fixture with
reactStrictMode: falseexpects one. The latter exercises the complete path fromnext.config.tsthrough Vite's define replacement and the browser root wrapper.Validation
Fragment: expected2, received1.falseas though it were the string"false": expected1, received2.true, and explicitfalse.vinextpackage.Commands
Risk
Low. The change is confined to the App Router client root and its build-time boolean. React Strict Mode's additional checks are development-only, while an explicit
falseselectsFragment. Existing Pages Router behavior and defaults are unchanged. App Router applications may now expose non-idempotent development behavior that Strict Mode is intended to detect.References
StrictModeorFragmentnext.config.ts