Skip to content

Commit 29402f3

Browse files
authoredApr 24, 2021
Replace experimental reactMode with reactRoot (#24280)
* Remove reactMode config * Add config + warning * Tweak wording on warning * Tweak wording on warning * Don't default reactRoot for 10.x * yak shaving * Add warning when using old reactMode
1 parent 2743a74 commit 29402f3

File tree

5 files changed

+32
-29
lines changed

5 files changed

+32
-29
lines changed
 

‎.github/workflows/test_react_experimental.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ jobs:
2929
# needs: build
3030
env:
3131
NEXT_TELEMETRY_DISABLED: 1
32-
NEXT_PRIVATE_REACT_MODE: concurrent
3332
HEADLESS: true
3433
NEXT_PRIVATE_SKIP_SIZE_TESTS: true
34+
NEXT_PRIVATE_REACT_ROOT: 1
3535
strategy:
3636
fail-fast: false
3737
matrix:

‎packages/next/build/webpack-config.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1048,8 +1048,8 @@ export default async function getBaseWebpackConfig(
10481048
'process.env.__NEXT_STRICT_MODE': JSON.stringify(
10491049
config.reactStrictMode
10501050
),
1051-
'process.env.__NEXT_REACT_MODE': JSON.stringify(
1052-
config.experimental.reactMode
1051+
'process.env.__NEXT_REACT_ROOT': JSON.stringify(
1052+
config.experimental.reactRoot
10531053
),
10541054
'process.env.__NEXT_OPTIMIZE_FONTS': JSON.stringify(
10551055
config.optimizeFonts && !dev

‎packages/next/client/index.tsx

+14-13
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,8 @@ export function renderError(renderErrorProps: RenderErrorProps): Promise<any> {
494494
}
495495

496496
let reactRoot: any = null
497-
let shouldUseHydrate: boolean = typeof ReactDOM.hydrate === 'function'
497+
let shouldHydrate: boolean = typeof ReactDOM.hydrate === 'function'
498+
498499
function renderReactElement(
499500
domEl: HTMLElement,
500501
fn: (cb: () => void) => JSX.Element
@@ -504,24 +505,24 @@ function renderReactElement(
504505
performance.mark('beforeRender')
505506
}
506507

507-
const reactEl = fn(
508-
shouldUseHydrate ? markHydrateComplete : markRenderComplete
509-
)
510-
if (process.env.__NEXT_REACT_MODE !== 'legacy') {
508+
const reactEl = fn(shouldHydrate ? markHydrateComplete : markRenderComplete)
509+
if (process.env.__NEXT_REACT_ROOT) {
511510
if (!reactRoot) {
512-
const opts = { hydrate: shouldUseHydrate }
513-
reactRoot =
514-
process.env.__NEXT_REACT_MODE === 'concurrent'
515-
? (ReactDOM as any).unstable_createRoot(domEl, opts)
516-
: (ReactDOM as any).unstable_createBlockingRoot(domEl, opts)
511+
const createRootName =
512+
typeof (ReactDOM as any).unstable_createRoot === 'function'
513+
? 'unstable_createRoot'
514+
: 'createRoot'
515+
reactRoot = (ReactDOM as any)[createRootName](domEl, {
516+
hydrate: shouldHydrate,
517+
})
517518
}
518519
reactRoot.render(reactEl)
519-
shouldUseHydrate = false
520+
shouldHydrate = false
520521
} else {
521522
// The check for `.hydrate` is there to support React alternatives like preact
522-
if (shouldUseHydrate) {
523+
if (shouldHydrate) {
523524
ReactDOM.hydrate(reactEl, domEl)
524-
shouldUseHydrate = false
525+
shouldHydrate = false
525526
} else {
526527
ReactDOM.render(reactEl, domEl)
527528
}

‎packages/next/next-server/server/config-shared.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export type NextConfig = { [key: string]: any } & {
6060
skipValidation?: boolean
6161
}
6262
turboMode: boolean
63+
reactRoot: boolean
6364
}
6465
}
6566

@@ -104,7 +105,6 @@ export const defaultConfig: NextConfig = {
104105
plugins: false,
105106
profiling: false,
106107
sprFlushToDisk: true,
107-
reactMode: (process.env.NEXT_PRIVATE_REACT_MODE as any) || 'legacy',
108108
workerThreads: false,
109109
pageEnv: false,
110110
optimizeImages: false,
@@ -115,6 +115,7 @@ export const defaultConfig: NextConfig = {
115115
externalDir: false,
116116
serialWebpackBuild: false,
117117
turboMode: false,
118+
reactRoot: Number(process.env.NEXT_PRIVATE_REACT_ROOT) > 0,
118119
},
119120
future: {
120121
strictPostcssConfiguration: false,

‎packages/next/next-server/server/config.ts

+13-12
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { loadEnvConfig } from '@next/env'
1313
export { DomainLocales, NextConfig, normalizeConfig } from './config-shared'
1414

1515
const targets = ['server', 'serverless', 'experimental-serverless-trace']
16-
const reactModes = ['legacy', 'blocking', 'concurrent']
1716

1817
const experimentalWarning = execOnce(() => {
1918
Log.warn(chalk.bold('You have enabled experimental feature(s).'))
@@ -36,6 +35,19 @@ function assignDefaults(userConfig: { [key: string]: any }) {
3635
delete userConfig.exportTrailingSlash
3736
}
3837

38+
if (typeof userConfig.experimental?.reactMode !== 'undefined') {
39+
console.warn(
40+
chalk.yellow.bold('Warning: ') +
41+
'The experimental "reactMode" option has been replaced with "reactRoot". Please update your next.config.js.'
42+
)
43+
if (typeof userConfig.experimental?.reactRoot === 'undefined') {
44+
userConfig.experimental.reactRoot = ['concurrent', 'blocking'].includes(
45+
userConfig.experimental.reactMode
46+
)
47+
}
48+
delete userConfig.experimental.reactMode
49+
}
50+
3951
const config = Object.keys(userConfig).reduce<{ [key: string]: any }>(
4052
(currentConfig, key) => {
4153
const value = userConfig[key]
@@ -435,17 +447,6 @@ export default async function loadConfig(
435447
: canonicalBase) || ''
436448
}
437449

438-
if (
439-
userConfig.experimental?.reactMode &&
440-
!reactModes.includes(userConfig.experimental.reactMode)
441-
) {
442-
throw new Error(
443-
`Specified React Mode is invalid. Provided: ${
444-
userConfig.experimental.reactMode
445-
} should be one of ${reactModes.join(', ')}`
446-
)
447-
}
448-
449450
if (hasNextSupport) {
450451
userConfig.target = process.env.NEXT_PRIVATE_TARGET || 'server'
451452
}

0 commit comments

Comments
 (0)
Please sign in to comment.