webpack自定义loader初探

最近负责的Weex项目涉及到一些构建上的问题,需要通过自定义webpack的loader去实现,于是学习了一下这方面的知识,写一篇文章做个总结,以免遗忘。

什么是loader

我们都知道webpack作为当下最火的一个前端构建工具,具有很多很实用的功能,loader就是其中之一。说的通俗一点,loader就是用于对模块的源码进行转换。对于做Android的同学,大家可以把它想象成gradle中的transform task。

loader怎么用

在平时的开发过程中,loader的使用也是非常常见的,我们可以在工程的webpack.config.js中定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}, {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
}

可以看到,对于css文件,我们使用css-loader,对于vue文件,我们使用vue-loader,对于图片文件,我们使用file-loader。这些loader会将对应的文件进行转换,构建出最终的产物。

如何自定义loader

有了上面的经验,我们该如何自定义一个loader呢?其实也是非常简单的。

首先我们创建一个js文件,就取名叫test-loader吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var loaderUtils = require('loader-utils');

module.exports = function(source) {
console.log("start process code...");

var options = loaderUtils.getOptions(this) || {};
if(options !== {}) {
var replaceMap = options["replaceMap"];
for(var key in replaceMap) {
console.log(source);
source = source.replace(key, replaceMap[key]);
console.log(source);
}
}

return source;
};

这就是全部的代码了,其实一个loader内部就是一个node模块,代码的编写就和平时写node一样就ok了。

test-loader的逻辑就是获取到设置的option,并且做一个文本的替换。

假设我们还有2个js文件,分别是test.js和index.js

1
2
3
4
const str = 'test is loaded';
module.exports = str;

test.js
1
2
3
4
const test = require('./src/test');
console.log(test);

index.js

然后我们在webpack.config.js中加入我们自己的test-loader。

1
2
3
4
5
6
7
8
9
10
{
test: /\.js$/,
loader: 'test-loader',
exclude: /node_modules/,
options: {
replaceMap: {
"loaded": "yeah"
}
}
}

其中options中,我们将“loaded”字符串替换成“yeah”。

但是我们的loader并没有上传到npm中,所以我们还需要在webpack.config.js中加入下面这段代码:

1
2
3
resolveLoader: {
modules: [path.join(__dirname, './src/loaders'), 'node_modules']
}

用于加载本地loader。

这样我们最终构建出来的产物中,所有的“loaded”字符串就会被替换成“yeah”了。

小结

这篇文章非常浅显,主要就是讲了一下loader的使用方式,其实我们熟知的很多loader都是这么做的,只不过是业务逻辑上的复杂程度不同而已,大家也可以自己试试看。