2020-10-10 webpack 5.0.0 发布了,其中的一个变化是 Webpack 5 再也不为 Node.js 模块引入 Polyfills 了。前端
在早期,webpack 的目的是为了让大多数的 Node.js 模块运行在浏览器中,但现在模块的格局已经发生了变化,如今许多模块主要是为前端而编写。webpack <= 4 的版本中提供了许多 Node.js 核心模块的 polyfills,一旦某个模块引用了任何一个核心模块(如 cypto 模块),webpack 就会自动引入 polyfills。node
好比下面的代码:实现签名的一个函数。webpack
const crypto = require('crypto');// 将值经过私钥签名,由.分割原值和签名function sign (val, secret) { return val + '.' + crypto .createHmac('sha256', secret) .update(val) .digest('base64') .replace(/\=+$/, ''); };module.exports = sign;复制代码
代码中使用到了 crypto 模块,由于在浏览器环境下是没有 crypto 这个东西,因此要引入 polyfills 作兼容处理。保证在浏览器中能够正常运行。ios
引入 polyfills 致使的问题就是打包的体积变大了。(能够考虑不要使用 node 模块,其实 npm 上还有一些其它的模块,好比 crypto-js)web
怎么防止打包的时候把 crypto 模块打进去了,其实咱们能够在 package.json 里面配置 browser 字段,而后设置值 false 就能够。这样代码就只能在 node 环境下运行了。npm
{ "name": "webpack4", "version": "1.0.0", "description": "", "main": "index.js", "browser": {"crypto": false }, "scripts": {"webpck": "npx webpack" }, "keywords": [], "author": "", "license": "ISC", "dependencies": {"webpack": "^4.35.3","webpack-cli": "^3.1.0" } }复制代码
从 webpack 5 开始再也不自动引入这些 polyfills,而会专一于前端模块兼容。目的是提升 web 平台的兼容性。由于 node 模块自己就不是为浏览器设计的。json
一、因此尽可能使用前端兼容的模块。好比 axios 这样的库,便可以在浏览器中运行,也能够在 node 环境中运行。axios
二、能够手动为 Node.js 核心模块添加 polyfill。错误提示会告诉你如何作。浏览器
好比下面的使用 webpack5 打包,报错信息是这样的。而后按照报错信息改。ide
let path = require('path')module.exports = { mode: 'development', entry: './src/index.js', output: {filename: 'bundle.js',path: path.resolve(__dirname, 'dist'),library: 'result' }, resolve: {fallback: { "crypto": require.resolve("crypto-browserify"), "stream": require.resolve("stream-browserify") } }, }复制代码
三、在 package.json 中添加 browser 字段,使 node 模块与前端兼容。为浏览器提供其余的 dependencies 依赖。
下面 browser 字段的含义是在浏览器环境中把 crypto 模块替换为 crypto-js 模块。
{ "name": "webpack4", "version": "1.0.0", "description": "", "main": "index.js", "browser": {"crypto": "crypto-js" }, "scripts": {"webpck": "npx webpack" }, "keywords": [], "author": "", "license": "ISC", "dependencies": {"crypto-js": "^4.0.0","webpack": "^4.35.3","webpack-cli": "^3.1.0" } }复制代码
总结:由于 webpack 打包默认是输出到浏览器端,若是咱们在编写代码的时候引入了 node 的核心模块,此时 webpack5 就会抛出错误,提示咱们须要配置 polyfills 。解决办法有三个,第一就是不要去使用 node 模块,而是替换成其余的前端模块。第二就是本身配置 polyfills,第三就不让 node 模块打包进行。
若是咱们写的代码只运行在 node 环境,直接配置 taget 就能够。
let path = require('path')module.exports = { mode: 'development', entry: './src/index.js', output: {filename: 'bundle.js',path: path.resolve(__dirname, 'dist'),library: 'result' }, target: 'node'}复制代码
其实不多会用到 browser 字段。
这是 webpack4 升级到 webpack 5 的重大区别。若是你打包的时候发生报错,能够看看你是否引入了 node 模块致使的。