學習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的"套路"入門篇。