Skip to content

Commit

Permalink
Enable webpack5 for all apps (#25639)
Browse files Browse the repository at this point in the history
* Enable webpack 5 by default for all apps

Still provides a way to opt-out using `webpack5: false` in next.config.js. Also throws an error for `future.webpack5`.

* Update tests

* Update test to run on webpack 4 instead of webpack 5

* disable webpack5 for legacy tests

* Fix stats-config for webpack4

* update tests

* update size for webpack4 test

* move basic suite first

* update basic test

* Add logs

* remove outdated testFutureDependencies job

Co-authored-by: JJ Kasper <jj@jjsweb.site>
  • Loading branch information
timneutkens and ijjk authored Jun 7, 2021
1 parent 069f7e8 commit e1502bc
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 112 deletions.
36 changes: 4 additions & 32 deletions .github/workflows/build_test_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,15 @@ jobs:
steps:
- run: exit 0

testFutureDependencies:
name: Webpack 5 (Basic, Production, Acceptance)
testLegacyWebpack:
name: Webpack 4 (Basic, Production, Acceptance)
runs-on: ubuntu-latest
needs: build
env:
NEXT_TELEMETRY_DISABLED: 1
NEXT_TEST_JOB: 1
HEADLESS: true
NEXT_PRIVATE_TEST_WEBPACK5_MODE: 1
NEXT_PRIVATE_TEST_WEBPACK4_MODE: 1

steps:
- uses: actions/cache@v2
Expand All @@ -174,37 +174,9 @@ jobs:
path: ./*
key: ${{ github.sha }}

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

testLegacyWebpack:
name: 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
with:
fetch-depth: 25

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

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

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

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

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

testFirefox:
name: Test Firefox (production)
runs-on: ubuntu-latest
Expand Down
33 changes: 33 additions & 0 deletions errors/future-webpack5-moved-to-webpack5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# `future.webpack5` has been moved to `webpack5`

#### Why This Error Occurred

The `future.webpack5` option has been moved to `webpack5` in `next.config.js`.

#### Possible Ways to Fix It

If you had the value `true` you can removed the option as webpack 5 is now the default for all Next.js apps unless opted out.

If you had he value `false` you can update `next.config.js`:

Change `future.webpack5` to `webpack5`.

Current `next.config.js`:

```js
// next.config.js
module.exports = {
future: {
webpack5: false,
},
}
```

Updated `next.config.js`:

```js
// next.config.js
module.exports = {
webpack5: false,
}
```
20 changes: 11 additions & 9 deletions errors/webpack5.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

#### Why This Message Occurred

Next.js will soon adopt webpack 5 as the default for compilation. We've spent a lot of effort into ensuring the transition from webpack 4 to 5 will be as smooth as possible. For example Next.js now comes with both webpack 4 and 5 allowing you to adopt webpack 5 by adding a flag to your `next.config.js`:
Next.js has adopted webpack 5 as the default for compilation. We've spent a lot of effort into ensuring the transition from webpack 4 to 5 will be as smooth as possible. For example Next.js now comes with both webpack 4 and 5 allowing you to adopt webpack 5 by adding a flag to your `next.config.js`:

```js
module.exports = {
future: {
webpack5: true,
},
// Webpack 5 is enabled by default
// You can still use webpack 4 while upgrading to the latest version of Next.js by adding the "webpack5: false" flag
webpack5: false,
}
```

Adopting webpack 5 in your application has many benefits, notably:
Using webpack 5 in your application has many benefits, notably:

- Improved Disk Caching: `next build` is significantly faster on subsequent builds
- Improved Fast Refresh: Fast Refresh work is prioritized
Expand All @@ -22,11 +22,13 @@ Adopting webpack 5 in your application has many benefits, notably:
- Support for web workers using `new Worker(new URL("worker.js", import.meta.url))`
- Support for `exports`/`imports` field in `package.json`

In upcoming releases we'll gradually roll out webpack 5 to applications that are compatible with webpack 5:
In the past releases we have gradually rolled out webpack 5 to Next.js applications:

- In the next minor version we'll automatically opt-in applications without custom webpack configuration in `next.config.js`
- In the next minor version we'll automatically opt-in applications that do not have a `next.config.js`
- In the next major version we'll enable webpack 5 by default. You'll still be able to opt-out and use webpack 4 to help with backwards compatibility
- In Next.js 10.2 we automatically opted-in applications without custom webpack configuration in `next.config.js`
- In Next.js 10.2 we automatically opted-in applications that do not have a `next.config.js`
- In Next.js 11 webpack 5 was enabled by default for all applications. You can still opt-out and use webpack 4 to help with backwards compatibility using `webpack5: false` in `next.config.js`

In the next major version webpack 4 support will be removed.

#### Custom webpack configuration

Expand Down
10 changes: 7 additions & 3 deletions packages/next/next-server/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ export type NextConfig = { [key: string]: any } & {
}
>
redirects?: () => Promise<Redirect[]>

trailingSlash?: boolean
webpack5?: false

future: {
/**
* @deprecated this options was moved to the top level
*/
webpack5?: false
strictPostcssConfiguration?: boolean
excludeDefaultMomentLocales?: boolean
webpack5?: boolean
}
experimental: {
cpus?: number
Expand Down Expand Up @@ -112,10 +115,11 @@ export const defaultConfig: NextConfig = {
disableOptimizedLoading: true,
gzipSize: true,
},
webpack5:
Number(process.env.NEXT_PRIVATE_TEST_WEBPACK4_MODE) > 0 ? false : undefined,
future: {
strictPostcssConfiguration: false,
excludeDefaultMomentLocales: false,
webpack5: Number(process.env.NEXT_PRIVATE_TEST_WEBPACK5_MODE) > 0,
},
serverRuntimeConfig: {},
publicRuntimeConfig: {},
Expand Down
40 changes: 12 additions & 28 deletions packages/next/next-server/server/config-utils-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ export function install(useWebpack5: boolean) {

export type CheckReasons =
| 'test-mode'
| 'no-config'
| 'default'
| 'flag-disabled'
| 'future-flag'
| 'no-future-flag'
| 'no-webpack-config'
| 'webpack-config'

export type CheckResult = {
enabled: boolean
Expand All @@ -43,20 +41,18 @@ export async function shouldLoadWithWebpack5(
cwd: dir,
})

if (Number(process.env.NEXT_PRIVATE_TEST_WEBPACK5_MODE) > 0) {
if (Number(process.env.NEXT_PRIVATE_TEST_WEBPACK4_MODE) > 0) {
return {
enabled: true,
enabled: false,
reason: 'test-mode',
}
}

// No `next.config.js`:
// Use webpack 5 by default in apps that do not have next.config.js
if (!path?.length) {
// Uncomment to add auto-enable when there is no next.config.js
// Use webpack 5 by default in new apps:
return {
enabled: true,
reason: 'no-config',
reason: 'default',
}
}

Expand All @@ -69,33 +65,21 @@ export async function shouldLoadWithWebpack5(
userConfigModule.default || userConfigModule
)

// Opted-in manually
if (userConfig.future?.webpack5 === true) {
if (userConfig.future?.webpack5) {
return {
enabled: true,
enabled: false,
reason: 'future-flag',
}
}

// Opted-out manually
if (userConfig.future?.webpack5 === false) {
if (userConfig.webpack5 === false) {
return {
enabled: false,
reason: 'no-future-flag',
}
}

// Uncomment to add auto-enable when there is no custom webpack config
// The user isn't configuring webpack
if (!userConfig.webpack) {
return {
enabled: true,
reason: 'no-webpack-config',
reason: 'flag-disabled',
}
}

return {
enabled: false,
reason: 'webpack-config',
enabled: true,
reason: 'default',
}
}
40 changes: 22 additions & 18 deletions packages/next/next-server/server/config-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,10 @@ export { install, shouldLoadWithWebpack5 }

function reasonMessage(reason: CheckReasons) {
switch (reason) {
case 'future-flag':
return 'future.webpack5 option enabled'
case 'no-future-flag':
return 'future.webpack5 option disabled'
case 'no-config':
return 'no next.config.js'
case 'webpack-config':
return 'custom webpack configuration in next.config.js'
case 'no-webpack-config':
return 'no custom webpack configuration in next.config.js'
case 'default':
return 'Enabled by default'
case 'flag-disabled':
return 'webpack5 flag is set to false in next.config.js'
case 'test-mode':
return 'internal test mode'
default:
Expand All @@ -27,7 +21,8 @@ function reasonMessage(reason: CheckReasons) {
}

export async function loadWebpackHook(phase: string, dir: string) {
let useWebpack5 = false
let useWebpack5 = true
let usesRemovedFlag = false
const worker: any = new Worker(
path.resolve(__dirname, './config-utils-worker.js'),
{
Expand All @@ -37,13 +32,16 @@ export async function loadWebpackHook(phase: string, dir: string) {
)
try {
const result: CheckResult = await worker.shouldLoadWithWebpack5(phase, dir)
// Don't log which webpack version is being used when booting production server as it's not used after build
if (phase !== PHASE_PRODUCTION_SERVER) {
Log.info(
`Using webpack ${result.enabled ? '5' : '4'}. Reason: ${reasonMessage(
result.reason
)} https://nextjs.org/docs/messages/webpack5`
)
if (result.reason === 'future-flag') {
usesRemovedFlag = true
} else {
if (phase !== PHASE_PRODUCTION_SERVER) {
Log.info(
`Using webpack ${result.enabled ? '5' : '4'}. Reason: ${reasonMessage(
result.reason
)} https://nextjs.org/docs/messages/webpack5`
)
}
}

useWebpack5 = Boolean(result.enabled)
Expand All @@ -54,5 +52,11 @@ export async function loadWebpackHook(phase: string, dir: string) {
worker.end()
}

if (usesRemovedFlag) {
throw new Error(
'`future.webpack5` in `next.config.js` has moved to the top level `webpack5` flag https://nextjs.org/docs/messages/future-webpack5-moved-to-webpack5'
)
}

install(useWebpack5)
}
11 changes: 2 additions & 9 deletions test/.stats-app/stats-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ module.exports = {
content: `
module.exports = {
generateBuildId: () => 'BUILD_ID',
future: {
webpack5: true
},
webpack(config) {
config.optimization.minimize = false
config.optimization.minimizer = undefined
Expand Down Expand Up @@ -138,9 +135,7 @@ module.exports = {
content: `
module.exports = {
generateBuildId: () => 'BUILD_ID',
future: {
webpack5: false
},
webpack5: false,
webpack(config) {
config.optimization.minimize = false
config.optimization.minimizer = undefined
Expand All @@ -157,9 +152,7 @@ module.exports = {
content: `
module.exports = {
generateBuildId: () => 'BUILD_ID',
future: {
webpack5: false
}
webpack5: false
}
`,
},
Expand Down
6 changes: 6 additions & 0 deletions test/integration/basic/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ describe('Basic Features', () => {

it('should polyfill Node.js modules', async () => {
const browser = await webdriver(context.appPort, '/node-browser-polyfills')

console.error({
logs: await browser.log('browser'),
content: await browser.eval('document.documentElement.innerHTML'),
})

await browser.waitForCondition('window.didRender')

const data = await browser
Expand Down
2 changes: 2 additions & 0 deletions test/integration/config/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const withSass = require('@zeit/next-sass')
const path = require('path')
module.exports = withCSS(
withSass({
// @zeit/next-sass is not supported with webpack 5
webpack5: false,
onDemandEntries: {
// Make sure entries are not getting disposed.
maxInactiveAge: 1000 * 60 * 60,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const withCSS = require('@zeit/next-css')

module.exports = withCSS({
// @zeit/next-css is not supported with webpack 5
webpack5: false,
onDemandEntries: {
// Make sure entries are not getting disposed.
maxInactiveAge: 1000 * 60 * 60,
Expand Down
3 changes: 0 additions & 3 deletions test/integration/externals/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,4 @@ module.exports = {

return config
},
future: {
webpack5: true,
},
}
4 changes: 3 additions & 1 deletion test/integration/fallback-modules/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ describe('Build Output', () => {
expect(parseFloat(indexSize)).toBeGreaterThanOrEqual(2)
expect(indexSize.endsWith('kB')).toBe(true)

expect(parseFloat(indexFirstLoad)).toBeLessThanOrEqual(67.9)
expect(parseFloat(indexFirstLoad)).toBeLessThanOrEqual(
process.env.NEXT_PRIVATE_TEST_WEBPACK4_MODE ? 68 : 67.9
)
expect(parseFloat(indexFirstLoad)).toBeGreaterThanOrEqual(60)
expect(indexFirstLoad.endsWith('kB')).toBe(true)
})
Expand Down
5 changes: 4 additions & 1 deletion test/integration/legacy-sass/next.config.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
const withSass = require('@zeit/next-sass')
module.exports = withSass()
module.exports = withSass({
// @zeit/next-sass is not supported with webpack 5
webpack5: false,
})
Loading

0 comments on commit e1502bc

Please sign in to comment.