What
在項目開發過程中,我們會使用到大量第三方的npm包,這些包大部分使用了 es中新的語法編寫 ,但是在發佈的時候,它們有些是經過 babel,tsc, esbuild 等工具轉換後發佈的,有的則沒有轉換直接發佈到 npm 中,
所以當我們在 webpack 中使用這樣的包時,可能會看到如下報錯:
Why
上面的截圖中使用了一個叫 screenfull 的包,點進去一看,原來是代碼中使用了?.
運算符,而在 webpack.config.js 中,由於 exclude 被設置爲整個 node_modules, 從而使 babel 跳過了對 screenfull 的轉換:
module: {
rules: [
{
test: /\.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "defaults" }]
]
}
}
}
]
}
How
這時,我們需要修改 exclude 的配置,確保報錯的 npm 中的包的代碼被轉換。exclude,include 作爲一個 Condition, 可以是下面的形式:
- 字符串:匹配輸入必須以提供的字符串開始。是的。目錄絕對路徑或文件絕對路徑。
- 正則表達式:test 輸入值,如
/node_modules/
。 - 函數:調用輸入的函數,必須返回一個真值(truthy value)以匹配。
- 條件數組:至少滿足一個匹配條件, 如
[/node_modules/, /lib/]
- 對象:所有屬性對應的 condition 都要滿足。每個屬性都有一個定義行爲。
所以上面的問題可以這樣來配置:
module: {
rules: [
{
test: /\.(?:js|mjs|cjs)$/,
+ exclude: {and: [/node_modules/], not: [/screenfull/] }, //screenfull是報錯的npm 包
- exclude: /node_modules/,
}
]
}
除此以外,我們也可以定義一個condition函數,來完成同樣的功能:
module: {
rules: [
{
test: /\.(?:js|mjs|cjs)$/,
exclude: (filepath) => {
if (/node_modules/.test(filepath)) {
if (/screenfull/.test(filepath)) {
return false;
}
return true;
}
return false
}
}
]
}