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的”套路”入門篇。

參考

來源:https://juejin.im/post/5abf22b3f265da2391483df3

相關文章