再也不爲 Node.js 模塊引入 Polyfills

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

相關文章
相關標籤/搜索