如何使webpack編譯 node_modules 中的 npm 包

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
      }
    }
  ]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章