前言
Loader就像一个翻译员,能将源文件经过转化后输出新的结果,并且这个文件还可以链式地经过多个翻译员翻译。在开发Loader的时候,应该遵循单一职责原则,只需要完成一种转换,开发的过程中我们只关心Loader的输入和输出。webpack是运行在Node.js上的,一个Loader就是一个Node模块。这个模块需要导出一个函数,这个导出的函数的工作就是获得处理前的原内容,对原内容执行处理返回处理后的内容。
一个最简单的Loader
一个最简单的loader源码如下
module.exports = function (source) {
//source为compiler 传递给 Loader 的一个文件的原内容
//该函数需要返回处理后的内容,为了简单起见,直接将原内容返回了,相当于该Loader没有做任何转换
return source
}开始开发之前
- 获取
Loader的options
在开发一个Loader的时候,要获取传入的options,需要这样做const loaderUtils = require('loader-utils') module.exports = function (source) { //获取用户传入的options const options = loaderUtils.getOptions(this) return source } - 同步与异步
Loader有同步和异步之分,上面介绍的Loader是同步的Loader,但在某些场景下转换的步骤只能是异步完成的,例如我们需要通过网络请求才能得出结果,如果采用同步的方式,则网络请求会阻塞整个构建,导致构建非常缓慢。
如果是异步转换,我们需要这样做module.exports = function (source) { //告诉webpack此次转换是异步的,Loader会在callback回调结果 var callback = this.async() asyncOperation(source,function(err,result,sourceMaps,ast){ callback(err,result,sourceMaps,ast) }) } - 加载本地
Loader
假设本地项目的Loader处于./src/loaders/myLoader中,需要如下配置module.exports = { resolveLoader:{ //去哪些目录寻找loaders 有先后之分 modules:['node_modules','./src/loaders'] } }或者我们也可以这样配置,直接加载对应的Loader处理对应的文件const path = require('path') module.exports = { module: { rules: [{ test: /\.js$/, use: [{ loader: path.resolve('loaders/test.js') }], }] }, }
在webpack.config.js中加上以上配置后,webpack先会去node_modules目录下寻找,如果找不到就会去./src/loaders下查找
开发我们的Loader
我们现在写一个简单的Loader,这个Loader的作用就是将JavaScript文件内容里面的字符串love转换成 ❤ 。webpac.config.js的配置如下
//webpack.config.js
const path = require('path')
module.exports = {
entry: './index.js',
module: {
rules: [{
test: /\.js$/,
use: [{
loader: path.resolve('loaders/test.js')
}],
}]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}我们自己写的Loader代码如下
//test.js
module.exports = function (source) {
const regExp = new RegExp("love", "ig")
const result = source.replace(regExp, "❤")
return result
}入口文件index.js里只有一行代码,即 module.exports="I love you" 执行打包命令npx webpack
可以看到打包后的文件bundle.js中
([function (e, t) {
e.exports = "I ❤ TAPD"
}])我们的字符'love'已经被转换成了❤

京公网安备 11010502036488号