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 模塊致使的。