创建自己的Loader
- Loader是用于对模块的源代码进行转换(处理),
css-loader、style-loader、babel-loader
等。 - Loader本质上是一个导出为函数的JavaScript模块;
- loader runner库会调用这个函数,然后将上一个loader产生的结果或者资源文件传入进去;
- 编写一个hy-loader01.js模块这个函数会接收三个参数:
content:
资源文件的内容;map:
sourcemap相关的数据;meta:
一些元数据;
module.exports = function(content,map,meta){
console.log(content)
return content
}
在加载某个模块时,引入loader
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './build'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/i,
use: [
"./loaders/hy-loader01.js"
]
}
]
}
}
resolveLoader属性
module.exports = {
resolveLoader: {
modules: ['node_modules', './loaders'], // 指定查找 loader 模块的目录
extensions: ['.js', '.json'], // 支持解析的文件扩展名
alias: {
// 配置 loader 别名
'my-loader': 'path/to/my-loader',
},
},
module: {
rules: [
{
test: /\.js$/,
use: [
'my-loader', // 使用别名配置的 loader
'babel-loader',
],
},
],
},
};
modules:
指定 Webpack 在解析 loader 模块时的查找目录。例如,配置了[‘node_modules’, ‘./loaders’],Webpack 将首先在node_modules目录下查找,如果找不到,会再去./loaders目录下查找。
extensions:
配置解析 loader 模块时支持的文件扩展名。例如,配置了[‘.js’, ‘.json’],Webpack 在解析 loader 模块时会尝试添加这些扩展名,以匹配模块文件。
alias:
配置 loader 模块的别名。例如,配置了’my-loader’: ‘path/to/my-loader’,在使用 loader 时,可以直接使用’my-loader’作为别名,Webpack 会根据该配置找到对应的 loader 模块。
需要注意的是,resolveLoader配置项的设置只影响到加载 loader 模块的解析过程,并不会影响其他模块的解析。一般情况下,不需要频繁地配置resolveLoader,只有在需要自定义 loader 解析规则或者配置 loader 别名时才需要使用。
loader的执行顺序
从后向前、从右向左的
pitch-loader和enforce
- 事实上还有另一种Loader,称之为PitchLoader:
module.exports.pitch = function(){
console.log("loader01 pitch")
}
执行顺序和enforce
- 其实这也是为什么loader的执行顺序是相反的:
- run-loader先优先执行PitchLoader,在执行PitchLoader时进行loaderIndex++;
- run-loader之后会执行NormalLoader,在执行NormalLoader时进行loaderIndex–;
- 那么,能不能改变它们的执行顺序呢?
- 我们可以拆分成多个Rule对象,通过enforce来改变它们的顺序;
- enforce一共有四种方式:
- 默认所有的loader都是normal;
- 在行内设置的loader是inline(在前面将css加载时讲过,import ‘loader1!loader2!./test.js’);
- 也可以通过enforce设置 pre 和 post;
- 在Pitching和Normal它们的执行顺序分别是:
- post, inline, normal, pre;
- pre, normal, inline, post;
同步的Loader
- 默认创建的Loader就是同步的Loader;
- 这个Loader必须通过 return 或者 this.callback 来返回结果,交给下一个loader来处理;
- 通常在有错误的情况下,我们会使用 this.callback;
- this.callback的用法如下:
- 第一个参数必须是 Error 或者 null;
- 第二个参数是一个 string或者Buffer;
module.exports = function(content){
console.log('loader01',content)
this.callback(null,content)
}
异步的Loader
- 有时候我们使用Loader时会进行一些异步的操作;
- 我们希望在异步操作完成后,再返回这个loader处理的结果;
- 这个时候我们就要使用异步的Loader了;
- loader-runner已经在执行loader时给我们提供了方法,让loader变成一个异步的loader:
module.exports = function(content){
const callback = this.async()
setTimeout(()=>{
console.log("loader01",content)
callback(null,content)
},1000)
}
传入和获取参数
- 在使用loader时,传入参数
- 我们可以通过一个webpack官方提供的一个解析库 loader-utils,安装对应的库。
校验参数
- 我们可以通过一个webpack官方提供的校验库 schema-utils,安装对应的库
babel-loader案例
- 我们知道babel-loader可以帮助我们对JavaScript的代码进行转换,这里我们定义一个自己的babel-loader: