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

feat: add experimental.fallbackNodePolyfills flag #39248

Merged
merged 9 commits into from Aug 26, 2022
123 changes: 68 additions & 55 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1577,61 +1577,74 @@ export default async function getBaseWebpackConfig(
},
{
resolve: {
// Full list of old polyfills is accessible here:
// https://github.com/webpack/webpack/blob/2a0536cf510768111a3a6dceeb14cb79b9f59273/lib/ModuleNotFoundError.js#L13-L42
fallback: {
assert: require.resolve('next/dist/compiled/assert'),
buffer: require.resolve('next/dist/compiled/buffer/'),
constants: require.resolve(
'next/dist/compiled/constants-browserify'
),
crypto: require.resolve(
'next/dist/compiled/crypto-browserify'
),
domain: require.resolve(
'next/dist/compiled/domain-browser'
),
http: require.resolve('next/dist/compiled/stream-http'),
https: require.resolve(
'next/dist/compiled/https-browserify'
),
os: require.resolve('next/dist/compiled/os-browserify'),
path: require.resolve(
'next/dist/compiled/path-browserify'
),
punycode: require.resolve(
'next/dist/compiled/punycode'
),
process: require.resolve('./polyfills/process'),
// Handled in separate alias
querystring: require.resolve(
'next/dist/compiled/querystring-es3'
),
stream: require.resolve(
'next/dist/compiled/stream-browserify'
),
string_decoder: require.resolve(
'next/dist/compiled/string_decoder'
),
sys: require.resolve('next/dist/compiled/util/'),
timers: require.resolve(
'next/dist/compiled/timers-browserify'
),
tty: require.resolve(
'next/dist/compiled/tty-browserify'
),
// Handled in separate alias
// url: require.resolve('url/'),
util: require.resolve('next/dist/compiled/util/'),
vm: require.resolve('next/dist/compiled/vm-browserify'),
zlib: require.resolve(
'next/dist/compiled/browserify-zlib'
),
events: require.resolve('next/dist/compiled/events/'),
setImmediate: require.resolve(
'next/dist/compiled/setimmediate'
),
},
fallback:
config.experimental.fallbackNodePolyfills === false
? {}
: {
assert: require.resolve(
'next/dist/compiled/assert'
),
buffer: require.resolve(
'next/dist/compiled/buffer/'
),
constants: require.resolve(
'next/dist/compiled/constants-browserify'
),
crypto: require.resolve(
'next/dist/compiled/crypto-browserify'
),
domain: require.resolve(
'next/dist/compiled/domain-browser'
),
http: require.resolve(
'next/dist/compiled/stream-http'
),
https: require.resolve(
'next/dist/compiled/https-browserify'
),
os: require.resolve(
'next/dist/compiled/os-browserify'
),
path: require.resolve(
'next/dist/compiled/path-browserify'
),
punycode: require.resolve(
'next/dist/compiled/punycode'
),
process: require.resolve('./polyfills/process'),
// Handled in separate alias
querystring: require.resolve(
'next/dist/compiled/querystring-es3'
),
stream: require.resolve(
'next/dist/compiled/stream-browserify'
),
string_decoder: require.resolve(
'next/dist/compiled/string_decoder'
),
sys: require.resolve('next/dist/compiled/util/'),
timers: require.resolve(
'next/dist/compiled/timers-browserify'
),
tty: require.resolve(
'next/dist/compiled/tty-browserify'
),
// Handled in separate alias
// url: require.resolve('url/'),
util: require.resolve('next/dist/compiled/util/'),
vm: require.resolve(
'next/dist/compiled/vm-browserify'
),
zlib: require.resolve(
'next/dist/compiled/browserify-zlib'
),
events: require.resolve(
'next/dist/compiled/events/'
),
setImmediate: require.resolve(
'next/dist/compiled/setimmediate'
),
},
},
},
],
Expand Down
3 changes: 3 additions & 0 deletions packages/next/server/config-schema.ts
Expand Up @@ -258,6 +258,9 @@ const configSchema = {
externalDir: {
type: 'boolean',
},
fallbackNodePolyfills: {
type: 'boolean',
},
forceSwcTransforms: {
type: 'boolean',
},
Expand Down
6 changes: 6 additions & 0 deletions packages/next/server/config-shared.ts
Expand Up @@ -145,6 +145,12 @@ export interface ExperimentalConfig {
}
swcPlugins?: Array<[string, Record<string, unknown>]>
largePageDataBytes?: number
/**
* If set to `false`, webpack won't fall back to polyfill Node.js modules in the browser
* Full list of old polyfills is accessible here:
* [webpack/webpack#ModuleNotoundError.js#L13-L42](https://github.com/webpack/webpack/blob/2a0536cf510768111a3a6dceeb14cb79b9f59273/lib/ModuleNotFoundError.js#L13-L42)
*/
fallbackNodePolyfills?: false
}

export type ExportPathMap = {
Expand Down
48 changes: 48 additions & 0 deletions test/production/disable-fallback-polyfills/index.test.ts
@@ -0,0 +1,48 @@
import { createNext } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'

describe('Disable fallback polyfills', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: {
'pages/index.js': `
import { useEffect } from 'react'
import crypto from 'crypto'

export default function Page() {
useEffect(() => {
crypto;
}, [])
return <p>hello world</p>
}
`,
},
dependencies: {},
})
await next.stop()
})
afterAll(() => next.destroy())

it('Fallback polyfills added by default', async () => {
const firstLoadJSSize = Number(
next.cliOutput.match(/○ \/\s{38}(\d*) kB\s{10}(?<firstLoad>\d*) kB/)
.groups.firstLoad
)
expect(firstLoadJSSize).not.toBeLessThan(200)
})

it('Build should fail, when fallback polyfilling is disabled', async () => {
await next.patchFile(
'next.config.js',
`module.exports = {
experimental: {
fallbackNodePolyfills: false
}
}`
)

await expect(next.start()).rejects.toThrow(/next build failed/)
})
})