Skip to content

Commit

Permalink
Bump minimum suggested React version (#21046)
Browse files Browse the repository at this point in the history
* Upgrade React version warning

* Fix font/stylesheet plugin

* Fix size-limit tests

* Fix build-output test

* Add tests for React 16

* Fix react-dom version
  • Loading branch information
devknoll committed Jan 15, 2021
1 parent 005a8ab commit cd5ea7d
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 48 deletions.
34 changes: 30 additions & 4 deletions .github/workflows/build_test_deploy.yml
Expand Up @@ -154,7 +154,7 @@ jobs:
- run: exit 0

testFutureDependencies:
name: React 17 + webpack 5 (Basic, Production, Acceptance)
name: Webpack 5 (Basic, Production, Acceptance)
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
Expand All @@ -171,16 +171,42 @@ jobs:
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: cat package.json | jq '.resolutions.react = "^17.0.1"' > package.json.tmp && mv package.json.tmp package.json
- run: yarn install --check-files
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: yarn list webpack
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: xvfb-run node run-tests.js test/integration/{link-ref,production,basic,async-modules,ssr-ctx}/test/index.test.js test/acceptance/*.test.js
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

testLegacyReact:
name: React 16 + Webpack 4 (Basic, Production, Acceptance)
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
NEXT_TEST_JOB: 1
HEADLESS: true

steps:
- uses: actions/checkout@v2

- run: echo ::set-output name=DOCS_CHANGE::$(node skip-docs-change.js echo 'docs-only')
id: docs-change

- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: cat package.json | jq '.resolutions.react = "^16.14.0"' > package.json.tmp && mv package.json.tmp package.json
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: cat package.json | jq '.resolutions."react-dom" = "^17.0.1"' > package.json.tmp && mv package.json.tmp package.json
- run: cat package.json | jq '.resolutions."react-dom" = "^16.14.0"' > package.json.tmp && mv package.json.tmp package.json
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: yarn install --check-files
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: yarn list webpack react react-dom
- run: yarn list react react-dom
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs-only' }}

- run: xvfb-run node run-tests.js test/integration/{link-ref,production,basic,async-modules,ssr-ctx,worker-loader}/test/index.test.js test/acceptance/*.test.js
Expand Down
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 @@ -115,8 +115,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')
.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)
})
})

0 comments on commit cd5ea7d

Please sign in to comment.