先直接來看代碼:
module.exports = function(source){
return source.replace('Webpack', 'JavaScript');
}
這三行代碼就實現了一個最簡單的Loader,它的作用是將源碼中出現的所有’Webpack’替換成’JavaScript’。
參數source
就是所處理的文件的代碼,是一個字符串。
所導出的函數必須是使用function
關鍵字聲明的,不可以使用箭頭函數,因爲Webpack會修改函數的this
,而箭頭函數沒有自己的this
,所以可能會出錯。
寫好的Loader就可以在配置文件中引入使用:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js/,
use: [path.resolve(__dirname, './loader/replaceLoader.js')]
}]
}
}
一般我們使用的Loader都是通過npm
或者yarn
安裝的,那麼配置的時候直接寫Loader名即可,然而自己寫的Loader則需要寫絕對路徑。
這裏岔開一下,如果我們希望自己寫的Loader也能直接通過Loader名的方式引用,只需要配置resolveLoader
即可:
module.exports = {
...,
resolveLoader: {
modules: ['./node_modules', './loader']
}
}
上述配置的意思是當需要使用Loader的時候,先去./node_modules
裏尋找,找不到就到./lodaer
目錄裏去找。
配置完成之後就可以打包了,沒有問題的話就能看到打包生成的文件出現了我們希望的變化。
我們在使用第三方Loader的時候,經常會通過options
來爲Loader進行一些配置,那麼我們自己寫的Loader該怎麼接受並處理這些options
呢?
首先現在配置文件裏進行配置:
module.exports = {
...,
module: {
rules: [{
test: /\.js$/,
use: [{
loader: path.resolve(__dirname, './loader/replaceLoader.js'),
options: {
name: 'CSS'
}
}]
}]
}
}
上面的配置項爲我們寫的Loader傳入了一個 name
option。那麼,我們可以在Loader之中,通過this.query.name
得到我們傳入的參數。
module.exports = function(source) {
return source.replace('Webpack', this.query.name);
}
這樣預期打包的結果就應該是console.log('Hello CSS')
。
除了用直接return的方法,還可以通過this.callback
來返回處理後的結果。
module.exports = function(source) {
const result = source.replace('Webpack', this.query.name);
this.callback(null, result);
}
this.callback
可以接受四個參數,分別是錯誤信息,處理後的結果,sourceMap,和一些額外信息。
如果說希望在Loader裏面執行一些異步的代碼,則需要調用this.async()
。
module.exports = function(source) {
let result = null;
const callback = this.async();
setTimeout(()=>{
result = source.replace('Webpack', this.query.name);
callback(null, result);
}, 1000)
}
this.async
返回的結果就是一個this.callback
。
之前我們是通過this.query
來獲取我們在配置文件中傳入的配置項。而Webpack的官方文檔推薦的是通過loader-utils
這個庫來獲取。
const loaderUtils = require('loader-utils');
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
return source.replace('Webpack', options.name);
}
```’