webpack筆記-loader的詳細使用介紹(四)


loader 基本上都是第三方類庫,使用時需要安裝,有一些 loader 還需要安裝額外的類庫,例如 less-loader 需要 less,babel-loader 需要 babel 等。

loader 匹配規則

loader的配置是放在 module 字段下,如下代碼前面提到過:

module.exports = {
  // ...
  module: {
    rules: [ 
      {
        test: /\.jsx?/,
        include: [
          path.resolve(__dirname, 'src'), // 指定哪些路徑下的文件需要經過 loader 處理
        ],
        use: {
          loader: 'babel-loader', // 指定使用的 loader
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      }, // 一個 object 即一條規則
      // ...
    ],
  },
}

loader 的匹配規則中有兩個最關鍵的因素:一個是匹配條件,一個是匹配規則后的應用。

匹配條件通常都使用請求資源文件的絕對路徑來進行匹配,在官方文檔中稱為 resource,除此之外還有比較少用到的 issuer,則是聲明依賴請求的源文件的絕對路徑。

如下例子:

printer.js
// Resource: greeter.js, Issuer: printer.js 
import greetSource from "./greeter"; 


index.js
// Resource: greeter.js, Issuer: index.js 
import greet from "./greeter"; 

issuer:和resource有異曲同工的作用,不過區別在於它是將這個rule應用於哪個文件以及這個文件所導入的所有依賴文件

舉個例子:在 /path/to/app.js 中聲明引入 import './src/style.scss',resource 是「/path/to/src/style.scss」,issuer 是「/path/to/app.js」,規則條件會對這兩個值來嘗試匹配。

上述代碼中的 test 和 include 都用於匹配 resource 路徑,是 resource.test 和 resource.include 的簡寫,你也可以這么配置:

module.exports = {
  // ...
  rules: [ 
      {
        resource: { // resource 的匹配條件
          test: /\.jsx?/, 
          include: [ 
            path.resolve(__dirname, 'src'),
          ],
        },
        // 如果要使用 issuer 匹配,便是 issuer: { test: ... }
        // ...
      },
      // ...
    ], 
}

issuer 規則匹配的場景比較少見,你可以用它來嘗試約束某些類型的文件中只能引用某些類型的文件。

當規則的條件匹配時,便會使用對應的 loader 配置,如上述例子中的 babel-loader

規則條件配置

webpack 的規則提供了多種配置形式:

  • { test: ... } 匹配特定條件
  • { include: ... } 匹配特定路徑
  • { exclude: ... } 排除特定路徑
  • { and: [...] }必須匹配數組中所有條件
  • { or: [...] } 匹配數組中任意一個條件
  • { not: [...] } 排除匹配數組中所有條件

上述的所謂條件的值可以是:

  • 字符串:必須以提供的字符串開始,所以是字符串的話,這里我們需要提供絕對路徑
  • 正則表達式:調用正則的 test 方法來判斷匹配
  • 函數:(path) => boolean,返回 true 表示匹配
  • 數組:至少包含一個條件的數組
  • 對象:匹配所有屬性值的條件

例子:

rules: [
  {
    test: /\.jsx?/, // 正則
    include: [
      path.resolve(__dirname, 'src'), // 字符串,注意是絕對路徑
    ], // 數組
    // ...
  },
  {
    resource: {
      test: {
        js: /\.js/,
        jsx: /\.jsx/,
      }, // 對象,不建議使用
      not: [
        (value) => { /* ... */ return true; }, // 函數,通常需要高度自定義時才會使用
      ],
    }
  },
],

test/include/exclude 是resource.(test/include/exclude) 的簡寫,and/or/not這些則需要放到resource中進行配置。

module type

webpack 4.x 版本強化了 module type,即模塊類型的概念,不同的模塊類型類似於配置了不同的 loader,webpack 會有針對性地進行處理,現階段實現了以下 5 種模塊類型。

  • javascript/auto:即 webpack 3 默認的類型,支持現有的各種 JS 代碼模塊類型 —— CommonJS、AMD、ESM
  • javascript/esm:ECMAScript modules,其他模塊系統,例如 CommonJS 或者 AMD 等不支持,是 .mjs 文件的默認類型
  • javascript/dynamic:CommonJS 和 AMD,排除 ESM
  • javascript/json:JSON 格式數據,require 或者 import 都可以引入,是 .json 文件的默認類型
  • webassembly/experimental:WebAssembly modules,當前還處於試驗階段,是 .wasm 文件的默認類型

如果不希望使用默認的類型的話,在確定好匹配規則條件時,我們可以使用 type 字段來指定模塊類型,例如把所有的 JS 代碼文件都設置為強制使用 ESM 類型:

{
  test: /\.js/,
  include: [
    path.resolve(__dirname, 'src'),
  ],
  type: 'javascript/esm', // 這里指定模塊類型
},

上述做法是可以幫助你規范整個項目的模塊系統,但是如果遺留太多不同類型的模塊代碼時,建議還是直接使用默認的javascript/auto

使用 loader 配置

如下使用use字段:

rules: [
  {
    test: /\.less/,
    use: [
      'style-loader', // 直接使用字符串表示 loader
      {
        loader: 'css-loader',
        options: {
          importLoaders: 1
        },
      }, // 用對象表示 loader,可以傳遞 loader 配置等
      {
        loader: 'less-loader',
        options: {
          noIeCompat: true
        }, // 傳遞 loader 配置
      },
    ],
  },
],

從上面的配置可以看到,use 字段可以是一個數組,也可以是一個字符串或者表示 loader 的對象。如果只需要一個 loader,也可以這樣:use: { loader: 'babel-loader', options: { ... } }

loader 應用順序

如下配置:

rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "eslint-loader",
  },
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "babel-loader",
  },
],

這樣無法法保證 eslint-loader 在 babel-loader 應用前執行。webpack 在 rules 中提供了一個 enforce 的字段來配置當前 rule 的 loader 類型,沒配置的話是普通類型,我們可以配置 pre 或 post,分別對應前置類型或后置類型的 loader。

eslint-loader 要檢查的是人工編寫的代碼,如果在 babel-loader 之后使用,那么檢查的是 Babel 轉換后的代碼,所以必須在 babel-loader 處理之前使用。

還有一種行內 loader,即我們在應用代碼中引用依賴時直接聲明使用的 loader,如 const json = require('json-loader!./file.json') 這種。不建議在應用開發中使用這種 loader

所有的 loader 按照前置 -> 行內 -> 普通 -> 后置的順序執行。所以當我們要確保 eslint-loader 在 babel-loader 之前執行時,可以如下添加 enforce 配置:

rules: [
  {
    enforce: 'pre', // 指定為前置類型
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "eslint-loader",
  },
]

使用 noParse

module.noParse 字段:可以用於配置哪些模塊文件的內容不需要進行解析。對於一些不需要解析依賴(即無依賴)的第三方大型類庫等,可以通過這個字段來配置,以提高整體的構建速度

注意:使用 noParse 進行忽略的模塊文件中不能使用import、require、define 等導入機制。

如下代碼:

module.exports = {
  // ...
  module: {
    noParse: /jquery|lodash/, // 正則表達式

    // 或者使用 function
    noParse(content) {
      return /jquery|lodash/.test(content)
    },
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM