1. 程式人生 > 其它 >webpack中loader使用和的工作原理

webpack中loader使用和的工作原理

技術標籤:webpack

loader的本質就是一個個的函式,在模組的編譯階段,會使用這些loader對原始碼進行處理,處理時,一般都會生成AST解析樹,這樣可以方便處理。

單個loader的使用沒有什麼好記錄的。

多個loader的使用是用一個use陣列,loader的使用順序是從下往上,也就是從use陣列的後往前執行的,下面的load1、loader2、loader3是我自己定義的loader

  use: [
    'loader1',
    'loader2',
    {
      loader: 'loader3',
      options: {
        name:
'jack', age: 18 } } ]

為了方便webpack找到loader,我們可以配置loader的解析規則,也就是解析路徑

  // 配置loader的解析規則
  resolveLoader: {
    // 指定找loader去哪個地方找
    modules: [
      // 這是預設值
      'node_modules',
      // 指定自己的
      path.resolve(__dirname, 'loaders')
    ]
  },

下面是loader1.js的內容,註釋已經寫得很清楚了,值得注意的是,module.exports和module.exports.pitch這兩個函式的執行順序是不一樣的,pitch是按照use陣列從前往後執行,所以比較適合用來對loader做一些預處理。

// loader本質上是一個函式
// content就是原始檔或者後一個loader傳過來的內容
// module.exports = function (content, map, meta) {
//   // console.log(content);
//   console.log(111);
//   return content;
// }

// 下面這種寫法和上面那種寫法是一樣的(同步loader)
module.exports = function (content, map, meta) {
  console.log(111);
  // 第一個引數是是否有錯誤,第三四個引數是可選的
  this.callback
(null, content, map, meta); } // pitch方法會根據loader的順序從前往後執行 module.exports.pitch = function () { console.log('pitch 111'); }

下面是loader2中的內容,不同於loader1的是,它是一個非同步的loader,非同步loader的好處就是它可以執行一些非同步操作,可以等非同步操作完之後再執行接下來的loader,效能更好。

// 非同步loader
module.exports = function (content, map, meta) {
  console.log(222);
  // 呼叫this.async() 告訴webpack這是一個非同步loader,需要等待 callback() 回撥之後再進行下一個loader處理 
  const callback = this.async();
  setTimeout(() => {
    callback(null, content)
  }, 1000)
  console.log('loader2中的非同步')
}
module.exports.pitch = function () {
  console.log('pitch 222');
}

下面是loader3中的內容,主要就是獲取loader的選項和驗證loader的選項

//getOptions方法可以來獲取loader的選項(這個包webpack沒有自帶)
const { getOptions } = require('loader-utils');
// 驗證options是不是符合規範(這個包是webpack內部自帶的包)
const { validate } = require('schema-utils');

const schema = require('./schema');

module.exports = function (content, map, meta) {
  // 獲取options
  const options = getOptions(this);

  console.log(333, options);

  // 校驗options是否合法,如果不合法,會報錯
  validate(schema, options, {
    name: 'loader3'
  })

  return content;
}
module.exports.pitch = function () {
  console.log('pitch 333');
}

這是schema.json中的內容

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "名稱~"
    }
  },
  "additionalProperties": true
}

下面是執行打包後的結果,可以看到loader中的內容按預期執行
在這裡插入圖片描述