webpack loader的"套路"

PlayerWho發表於2018-03-31

學習webpack loader,最後模擬style-loader、less-loader

什麼是loader

  • loader是一個函式,用來把檔案轉換成webpack識別的模組。

loader API

  • this.callback,一個可以同步或者非同步呼叫的可以返回多個結果的函式。
  • this.async,非同步的loader,返回this.callback

如何編寫loader

設定

  • webpack預設從node_modules裡找loader
  • 直接引入loader
{
  test: /\.js$/
  use: [
    {
      loader: path.resolve('path/to/loader.js'),
      options: {/* ... */}
    }
  ]
}
複製程式碼
  • 如果有多個loader的目錄,可以設定loader的目錄,webpack會從設定的目錄裡找到loader
resolveLoader: {
  modules: [
    'node_modules',
    path.resolve(__dirname, 'loaders')  //自己開發的loaders
  ]
}
複製程式碼

簡單用法

  • 當使用一個loader時,這個loader函式只有一個引數,引數是包含檔案內容的字串。
  • 同步loader可以返回一個代表模組轉化後的簡單的值
  • loader的返回值是javascript程式碼字串或者是Buffer
//css-loader 把css解析成webpack識別的模組
module.exports = function(source) {
  return `module.exports=${source}`;
}
複製程式碼

複雜用法

  • 當配置多個loader時,loader的執行順序時從右往左,右邊的執行結果作為引數傳到左邊。
  • less-loader把less轉化成css,傳給css-loader,css-loader把結果給style-loader,style-loader返回javascript程式碼字串。
{
    test:/\.less$/,
    use:[
        'style-loader','css-loader','less-loader'
    ]
}
複製程式碼

編寫原則

  • 單一職責。每個loader只負責一件事情。
  • 使用鏈式呼叫,確保loader的依賴關係的正確。
  • 無狀態性,確保loader在不同模組轉換之間不儲存狀態。每次執行都應該獨立於其他編譯模組以及相同模組之前的編譯結果。

loader工具庫

  • loader-utils,可以獲取loader的options
  • schema-utils,校驗loader的options的合法性

模擬less-loader、css-loader、style-loader

  • less-loader負責把less編譯成css
const less = require('less');
module.exports = function (source) {
    less.render(source, (e, output)=>{
        this.callback(e,output.css);    //把編譯後的css返回給下一個loader
    });
};

複製程式碼
  • css-loader負責把css交給下一個loader
module.exports = function (source) {
    return source;          //source是上個loader的返回值,如果沒有上一個loader,則是css的內容
};
複製程式碼
  • style-loader把css新增到style標籤裡
module.exports = function (source) {
    return `const e = document.createElement('style');
        e.innerHTML = ${JSON.stringify(source)};
        document.head.appendChild(e);`;
};
複製程式碼
  • 雖然每個loader功能簡單,但是loader之前職責單一,方便擴充套件。
總結

webpack loader的功能遠不止這些,本文算是編寫loader的"套路"入門篇。

參考

相關文章