先直接来看代码:
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);
}
```’