我们在配置webpack时,loader是必不可少了,我们可以借助babel-loader将es6的语法转义成浏览器能识别的es5的代码,借助sass-loader将scss转成css。那么我们自己是否可以自定义一些loader来包装代码呢,答案是肯定的,下面通过两个小例子使大家了解loader的基本用法。
1. 同步的loader
项目结构:
webpack-demo
|- package.json
|- webpack.config.js
|- /dist
|- /src
|- index.js
+ |- diyLoader.js
|- /node_modules
index.js
console.log("Hello Webpack")
diyLoader.js
module.exports = function(source) {
return source.replace(/Webpack/g, "Loader");
}
这就是一个最简单的loader,导出的是一个函数,函数的参数为源文件的内容或前一个loader的处理结果,函数的this包含了许多由Webpack和loader运行程序填充的方法或属性。函数的返回值应该是处理之后的字符串或缓冲区。
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js'
},
output: {
filename: 'bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin()
],
module: {
rules: [
{
test: /\.js$/,
use: path.resolve(__dirname, './src/diyLoader.js')
}
]
}
}
module.rules的配置说明当匹配到一个js文件时,就用src目录下的diyLoader.js的函数对该js文件做处理。
一个同步的loader就完成了,打包发现在控制台输出的内容为 "Hello Loader",而非 "Hello Webpack"。说明loader生效了。
还可以在loader中传递参数:
module: {
rules: [{
test: /\.js$/,
use: [{
loader: path.resolve(__dirname, './src/diyLoader.js'),
options: {
name: 'Loader'
}
}]
}]
}
diyLoader.js做相应的修改:
module.exports = function(source) {
return source.replace(/Webpack/g, this.query.name);
}
this.query包含了options对象的内容。this下包含了许多属性和方法,上面的return只返回了单个结果,当我们需要返回多个结果的时候,可以用this.callback
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
2. 异步的loader
一个loader一定要有返回值的,假如loader中是一个异步函数,那么返回值需要等异步方法执行完才能返回。所以就需要借助this.async来告诉webpack应等待异步结果,它返回this.callback()。具体实现修改diyLoader.js:
module.exports = function(source) {
const callback = this.async()
setTimeout(() => {
const result = source.replace(/webpack/g, this.query.name);
callback(null, result);
}, 1000)
}
这里的callback和this.callback是一样的。
不管是同步和异步的loader,它的作用都是在不修改源代码的情况下,对源代码进行包装,并返回包装之后的结果。如果你觉得看明白了,那么来看个更高级的用法吧 嘿,不要给async函数写那么多try/catch了