Skip to content

Instantly share code, notes, and snippets.

@ef4
Last active June 22, 2024 19:32
Show Gist options
  • Save ef4/d2cf5672a93cf241fd47c020b9b3066a to your computer and use it in GitHub Desktop.
Save ef4/d2cf5672a93cf241fd47c020b9b3066a to your computer and use it in GitHub Desktop.
Webpack 5 Node Polyfills Upgrade Cheatsheet

Webpack 5 Node Polyfills Upgrade Cheatsheet

Webpack 4 automatically polyfilled many Node APIs in the browser. This was not a great system, because it could lead to surprisingly giant libraries getting pulled into your app by accident, and it gave you no control over the exact versions of the polyfills you were using.

So Webpack 5 removed this functionality. That means you need to make changes if you were relying on those polyfills. This is a quick reference for how to replace the most common patterns.

List of polyfill packages that were used in webpack 4

For each automatically-polyfilled node package name on the left, this shows the name of the NPM package that was used to polyfill it on the right. Under webpack 5 you can manually install these packages and use them via resolve.fallback.

List taken from here.

{
	assert: "assert/",
	buffer: "buffer/",
	console: "console-browserify",
	constants: "constants-browserify",
	crypto: "crypto-browserify",
	domain: "domain-browser",
	events: "events/",
	http: "stream-http",
	https: "https-browserify",
	os: "os-browserify/browser",
	path: "path-browserify",
	punycode: "punycode/",
	process: "process/browser",
	querystring: "querystring-es3",
	stream: "stream-browserify",
	_stream_duplex: "readable-stream/duplex",
	_stream_passthrough: "readable-stream/passthrough",
	_stream_readable: "readable-stream/readable",
	_stream_transform: "readable-stream/transform",
	_stream_writable: "readable-stream/writable",
	string_decoder: "string_decoder/",
	sys: "util/",
	timers: "timers-browserify",
	tty: "tty-browserify",
	url: "url/",
	util: "util/",
	vm: "vm-browserify",
	zlib: "browserify-zlib"
}  

Replacing a node module with a polyfill package

Before:

{
  node: {
    // provide a polyfill for "path"
    path: true
  }
}

After:

{
  resolve: {
    fallback: {
      // make sure you `npm install path-browserify` to use this
      path: require.resolve('path-browserify')
    }
  }
}

Replacing a node module with an empty implementation

Before:

{
  node: {
    // provide an empty implementation of the "fs" module
    fs: false
  }
}

After:

{
  resolve: {
    fallback: {
      fs: false
    }
  }
}

Polyfilling globals

Three cheap and common Node global variables are still supported directly via webpack's node option:

{
  node: {
    // provides the global variable named "global"
    global: true,
    
    // provide __filename and __dirname global variables
    __filename: true,
    __dirname: true,
  }
}

Other globals like Buffer will need to be handled directly via ProvidePlugin or DefinePlugin. For example, to get the Buffer global variable you can use the buffer NPM package like:

import webpack from 'webpack';

module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      // you must `npm install buffer` to use this.
      Buffer: ['buffer', 'Buffer']
    })
  ]
}

Alternatively, to replace a global variable directly with a snippet of code, you can use DefinePlugin. For example, if you want to replace process.env.THING with false you can say:

import webpack from 'webpack';

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env.THING: 'false'
    })
  ]
}
@CodePolymath
Copy link

Would be helpful to mention what file these changes should be made in, where that file is located, etc. I am trying to solve a webpack 5 error and do not know where to make these changes.

+1 to this. I always LOVE devs talking at length about something that others clearly should know about, somehow, even though nothing is mentioned in the related docs and no examples are posted.

Might as well be talking to a brain surgeon or rocket scientist.

@CodePolymath
Copy link

If you got here by following links from the ember-auto-import docs, the README there shows how to pass webpack config.

I've read those docs, and I 100% disagree. I see you're a publisher of the ember-auto-import README, and it doesn't say a single thing about WHERE the webpack.config file is located, or what it is called, or its overall structure or purpose. Just a bunch of code snippets from INSIDE the file. You mention that ember-cli-build.js has a "webpack" section, but no explanation if that section supplants the webpack.config.js file or is meant as an addition to it.

BTW, saying in this gist that "you should have read something else, somewhere else first" is not helpful at all. This gist should contain all the relevant information.

Same thing about the ember-auto-import v2 "upgrade guide." NOTHING about where the webpack.config file is located, what the filename is, what it does or who needs it. That's like walking into the middle of a conversation and someone expecting you to know what it being discussed. As someone who has done a LOT of development (but none with webpack) I have found the official documentation severely lacking for ember-auto-import v2 and webpack.

Developers need to learn to make their documentation legible, comprehendible, relevant and applicable.

Not everyone looking for webpack related fixes have been using it for the last 5 years. Don't assume they have.

@veeramarni
Copy link

Any example with ESM, like webpack.config.mjs?

@nsunga
Copy link

nsunga commented Jul 14, 2023

omg this is amazing -- i think this u should suggest this to be an available doc in the webpack repo!

its been a nightmare finding full documentation for changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment