Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump minimum suggested React version #21046

Merged
merged 10 commits into from Jan 15, 2021
Merged
6 changes: 3 additions & 3 deletions errors/react-version.md
Expand Up @@ -5,7 +5,7 @@
Your project is using an old version of `react` or `react-dom` that does not
meet the suggested minimum version requirement.

Next.js suggests using, at a minimum, `react@16.10.0` and `react-dom@16.10.0`.
Next.js suggests using, at a minimum, `react@17.0.1` and `react-dom@17.0.1`.
Older versions of `react` and `react-dom` do work with Next.js, however, they do
not enable all of Next.js' features.

Expand Down Expand Up @@ -39,8 +39,8 @@ yarn add react@latest react-dom@latest
```json
{
"dependencies": {
"react": "^16.10.0",
"react-dom": "^16.10.0"
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}
```
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -110,8 +110,8 @@
"prettier": "2.0.5",
"pretty-bytes": "5.3.0",
"pretty-ms": "7.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-ssr-prepass": "1.0.8",
"release": "6.3.0",
"request-promise-core": "1.1.2",
Expand Down
Expand Up @@ -122,6 +122,10 @@ export class FontStylesheetGatheringPlugin {
parser.hooks.call
.for('__jsx')
.tap(this.constructor.name, jsxNodeHandler)
// New React JSX transform:
parser.hooks.call
.for('imported var')
devknoll marked this conversation as resolved.
Show resolved Hide resolved
.tap(this.constructor.name, jsxNodeHandler)
})
}
}
Expand Down
49 changes: 44 additions & 5 deletions packages/next/cli/next-build.ts
Expand Up @@ -55,11 +55,50 @@ const nextBuild: cliCommand = (argv) => {
printAndExit(`> No such directory exists as the project root: ${dir}`)
}

return build(dir, null, args['--profile'], args['--debug']).catch((err) => {
console.error('')
console.error('> Build error occurred')
printAndExit(err)
})
async function preflight() {
const { getPackageVersion } = await import('../lib/get-package-version')
const semver = await import('next/dist/compiled/semver').then(
(res) => res.default
)

const reactVersion: string | null = await getPackageVersion({
cwd: dir,
name: 'react',
})
if (
reactVersion &&
semver.lt(reactVersion, '17.0.1') &&
semver.coerce(reactVersion)?.version !== '0.0.0'
) {
Log.warn(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.' +
' Read more: https://err.sh/next.js/react-version'
)
} else {
const reactDomVersion: string | null = await getPackageVersion({
cwd: dir,
name: 'react-dom',
})
if (
reactDomVersion &&
semver.lt(reactDomVersion, '17.0.1') &&
semver.coerce(reactDomVersion)?.version !== '0.0.0'
) {
Log.warn(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.' +
' Read more: https://err.sh/next.js/react-version'
)
}
}
}

return preflight()
.then(() => build(dir, null, args['--profile'], args['--debug']))
.catch((err) => {
console.error('')
console.error('> Build error occurred')
printAndExit(err)
})
}

export { nextBuild }
8 changes: 4 additions & 4 deletions packages/next/cli/next-dev.ts
Expand Up @@ -68,11 +68,11 @@ const nextDev: cliCommand = (argv) => {
})
if (
reactVersion &&
semver.lt(reactVersion, '16.10.0') &&
semver.lt(reactVersion, '17.0.1') &&
semver.coerce(reactVersion)?.version !== '0.0.0'
) {
Log.warn(
'Fast Refresh is disabled in your application due to an outdated `react` version. Please upgrade 16.10 or newer!' +
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.' +
' Read more: https://err.sh/next.js/react-version'
)
} else {
Expand All @@ -82,11 +82,11 @@ const nextDev: cliCommand = (argv) => {
})
if (
reactDomVersion &&
semver.lt(reactDomVersion, '16.10.0') &&
semver.lt(reactDomVersion, '17.0.1') &&
semver.coerce(reactDomVersion)?.version !== '0.0.0'
) {
Log.warn(
'Fast Refresh is disabled in your application due to an outdated `react-dom` version. Please upgrade 16.10 or newer!' +
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.' +
' Read more: https://err.sh/next.js/react-version'
)
}
Expand Down
12 changes: 6 additions & 6 deletions test/integration/build-output/test/index.test.js
Expand Up @@ -94,17 +94,17 @@ describe('Build Output', () => {
expect(parseFloat(indexSize) - 266).toBeLessThanOrEqual(0)
expect(indexSize.endsWith('B')).toBe(true)

// should be no bigger than 62.2 kb
expect(parseFloat(indexFirstLoad)).toBeCloseTo(62.4, 1)
// should be no bigger than 63.8 kb
expect(parseFloat(indexFirstLoad)).toBeCloseTo(63.8, 1)
expect(indexFirstLoad.endsWith('kB')).toBe(true)

expect(parseFloat(err404Size) - 3.7).toBeLessThanOrEqual(0)
expect(err404Size.endsWith('kB')).toBe(true)

expect(parseFloat(err404FirstLoad)).toBeCloseTo(65.6, 1)
expect(parseFloat(err404FirstLoad)).toBeCloseTo(67, 1)
expect(err404FirstLoad.endsWith('kB')).toBe(true)

expect(parseFloat(sharedByAll)).toBeCloseTo(62.1, 1)
expect(parseFloat(sharedByAll)).toBeCloseTo(63.5, 1)
expect(sharedByAll.endsWith('kB')).toBe(true)

if (_appSize.endsWith('kB')) {
Expand All @@ -121,7 +121,7 @@ describe('Build Output', () => {
expect(parseFloat(mainSize) - 7.3).toBeLessThanOrEqual(0)
expect(mainSize.endsWith('kB')).toBe(true)

expect(parseFloat(frameworkSize) - 42).toBeLessThanOrEqual(0)
expect(parseFloat(frameworkSize) - 42.1).toBeLessThanOrEqual(0)
expect(frameworkSize.endsWith('kB')).toBe(true)
})

Expand Down Expand Up @@ -168,7 +168,7 @@ describe('Build Output', () => {
expect(parseFloat(indexSize)).toBeGreaterThanOrEqual(2)
expect(indexSize.endsWith('kB')).toBe(true)

expect(parseFloat(indexFirstLoad)).toBeLessThanOrEqual(65.2)
expect(parseFloat(indexFirstLoad)).toBeLessThanOrEqual(66.6)
expect(parseFloat(indexFirstLoad)).toBeGreaterThanOrEqual(60)
expect(indexFirstLoad.endsWith('kB')).toBe(true)
})
Expand Down
117 changes: 107 additions & 10 deletions test/integration/cli/test/index.test.js
Expand Up @@ -115,6 +115,69 @@ describe('CLI Usage', () => {
expect(code).toBe(expectedExitCode)
expect(signal).toBe(expectedExitSignal)
})

test('too old of react version', async () => {
const { stderr } = await runNextCommand(['build', dirOldReact], {
stderr: true,
})

expect(stderr).toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
})

test('too old of react-dom version', async () => {
const { stderr } = await runNextCommand(['build', dirOldReactDom], {
stderr: true,
})

expect(stderr).toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
})

test('experimental react version', async () => {
const { stderr } = await runNextCommand(['build', dirExperimentalReact], {
stderr: true,
})

expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
})

test('experimental react-dom version', async () => {
const { stderr } = await runNextCommand(
['build', dirExperimentalReactDom],
{
stderr: true,
}
)

expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
})

test('recommended react version', async () => {
const { stderr } = await runNextCommand(['build'], {
stderr: true,
})

expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
})

test('recommended react-dom version', async () => {
const { stderr } = await runNextCommand(['build'], {
stderr: true,
})

expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
})
})

describe('dev', () => {
Expand Down Expand Up @@ -296,9 +359,8 @@ describe('CLI Usage', () => {
})

expect(stderr).toMatch(
'Fast Refresh is disabled in your application due to an outdated `react` version'
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
expect(stderr).not.toMatch(`react-dom`)

await killApp(instance)
})
Expand All @@ -315,9 +377,8 @@ describe('CLI Usage', () => {
})

expect(stderr).toMatch(
'Fast Refresh is disabled in your application due to an outdated `react-dom` version'
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)
expect(stderr).not.toMatch('`react`')

await killApp(instance)
})
Expand All @@ -333,9 +394,9 @@ describe('CLI Usage', () => {
},
})

expect(stderr).not.toMatch('disabled')
expect(stderr).not.toMatch('outdated')
expect(stderr).not.toMatch(`react-dom`)
expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)

await killApp(instance)
})
Expand All @@ -351,9 +412,45 @@ describe('CLI Usage', () => {
},
})

expect(stderr).not.toMatch('disabled')
expect(stderr).not.toMatch('outdated')
expect(stderr).not.toMatch('`react`')
expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)

await killApp(instance)
})

test('recommended react version', async () => {
const port = await findPort()

let stderr = ''
let instance = await launchApp(dir, port, {
stderr: true,
onStderr(msg) {
stderr += msg
},
})

expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)

await killApp(instance)
})

test('recommended react-dom version', async () => {
const port = await findPort()

let stderr = ''
let instance = await launchApp(dir, port, {
stderr: true,
onStderr(msg) {
stderr += msg
},
})

expect(stderr).not.toMatch(
'React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11.'
)

await killApp(instance)
})
Expand Down
2 changes: 1 addition & 1 deletion test/integration/size-limit/test/index.test.js
Expand Up @@ -81,6 +81,6 @@ describe('Production response size', () => {
const delta = responseSizesBytes / 1024

// Expected difference: < 0.5
expect(delta).toBeCloseTo(282.6, 0)
expect(delta).toBeCloseTo(284.1, 0)
})
})
27 changes: 14 additions & 13 deletions yarn.lock
Expand Up @@ -12970,7 +12970,7 @@ promzard@^0.3.0:
dependencies:
read "1"

prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@15.7.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
dependencies:
Expand Down Expand Up @@ -13185,14 +13185,14 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"

react-dom@16.12.0:
version "16.12.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11"
react-dom@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.18.0"
scheduler "^0.20.1"

react-is@16.13.1, react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
version "16.13.1"
Expand All @@ -13209,13 +13209,13 @@ react-ssr-prepass@1.0.8:
dependencies:
object-is "^1.0.1"

react@16.12.0:
version "16.12.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83"
react@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"

read-cmd-shim@^1.0.1:
version "1.0.5"
Expand Down Expand Up @@ -14051,9 +14051,10 @@ saxes@^5.0.0:
dependencies:
xmlchars "^2.2.0"

scheduler@^0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4"
scheduler@^0.20.1:
version "0.20.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c"
integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
Expand Down