webpack4学习笔记(八)
编写一个loader
loader简单来说就是一个函数,通过一个函数参数接受到源代码,并在函数内部对代码作出变更
newLoader.js
module.exports = function (source) { // source代表的是源代码
return source.replace('world', ‘wang’) // 将代码中的world替换成wang
}
1
2
3
2
3
此时也需要在webpack.config.js中进行配置
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
module: {
rules: [{
test: /\.js/,
use: [
path.resolve(__dirname, './loaders/newLoaders.js') // 使用编写的loader
]
}]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
loader的使用还可以通过对象的形式使用例如
use: [
{
loader: path.resolve(__dirname, './loaders/newLoaders.js'),
options: {
name: 'Wang'
}
}
]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
loader有两种方式获取options中传递的参数
// 通过this.query访问参数
module.exports = function (source) {
return source.replace('world', this.query.name)
}
// 通过loader-utils处理参数
const loaderUtils = require('loader-utils');
module.exports = function (source) {
const options = loaderUtils.getOptions(this)
return source.replace('world', options.name)
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
如果想要返回err, 处理后源代码,source,或者其他内容,那么可以使用this.callback
const loaderUtils = require('loader-utils');
module.exports = function (source) {
const options = loaderUtils.getOptions(this)
const result = source.replace('world', options.name)
this.callback(null, result);
}
1
2
3
4
5
6
2
3
4
5
6
如果想要在函数内部做异步处理那么可以使用this.async()
const loaderUtils = require('loader-utils');
module.exports = function (source) {
const options = loaderUtils.getOptions(this)
const result = source.replace('world', options.name)
const callback = this.async(); // 声明一下内部有异步操作
setTimeout(() => {
const result = source.replace('dell', options.name);
callback(null, result);
}, 1000);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
如果我们有多个loader需要使用,我们可以通过resolveLoader来统一使用loaders文件中loader
如下配置
....
resolveLoader: {
modules: ['node_modules', './loaders']
},
module: {
rules: [{
test: /\.js/,
use: [
{
loader: 'replaceLoader',
},
{
loader: 'newloaders',
options: {
name: 'Wang'
}
},
]
}]
},
....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
编写loader需要注意的是不要使用箭头函数,会导致this指向错误
编写一个Plugin
plugin插件是一个类,如下是一个plugin的基本结构
class CopyrightWebpackPlugin {
constructor(options){
console.log(options) // options是插件传入的参数
}
apply(compiler) { // compiler是webpack的实例}
}
module.exports = CopyrightWebpackPlugin;
1
2
3
4
5
6
7
2
3
4
5
6
7
结构写好之后,需要webpack中引入使用插件
const path = require('path');
const CopyRightWebpackPlugin = require('./plugins/copyright-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
plugins: [
new CopyRightWebpackPlugin()
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
接下啦完善apply, 利用打包过程中emit的时刻来进行处理,添加一个copyright.txt文件,
apply(compiler) { // compiler是webpack的实例
compiler.hooks.compile.tap('CopyrightWebpackPlugin', (compilation) => {
console.log('compiler');
})
compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin', (compilation, cb) => {
compilation.assets['copyright.txt']= { // compilation.assets是打包生成的文件,可以向其中添加内容
source: function() {
return 'copyright by dell lee'
},
size: function() {
return 21;
}
};
cb();
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18