环境搭建
- 初始化项目
npm init -y
- 安装依赖
npm i webpack@5 webpack-cli@4 -D
- 目录结构
自定义 loader
- 暴露
loader
// loaders/loader1.js
// loader 是一个函数,接收要处理的内容,返回处理后的内容
module.exports = function (content) {
console.log(123)
return content
}
- 配置使用
loader
// /webpack.config.js
const path = require('path')
// 默认情况下,webpack@5 会以 /src/index.js 为入口,并打包到 /dist/main.js
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /.js$/,
loader: path.resolve(__dirname, 'loaders', 'loader1') // 使用 自定义 loader
}
]
}
}
- 运行测试:执行
npx webpack
- 可以看到我们自定义的
loader
执行了
配置 loader 查找路径
// /webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /.js$/,
loader: 'loader1' // 只需要写 loader 的名字即可
}
]
},
resolveLoader: {
modules: [
'node_modules', // webpack 默认寻找 loader 的位置
path.resolve(__dirname, 'loaders') // 将我们存放自定义 loader 的路径位置也配置进去
]
}
}
loader 执行顺序
- 创建多个
loader
并配置使用,如下
module.exports = function (content) {
console.log('loader 1')
return content
}
...
const path = require('path')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /.js$/,
use: ['loader1', 'loader2', 'loader3'] // 使用多个 loader
}
]
},
resolveLoader: {
...
}
}
-
运行测试
-
可以看到,
loader
是从右往左,从下往上依次执行的 -
使用
pitch
函数,可以使得loader
顺序执行,如下
module.exports = function (content) {
console.log('loader 1')
return content
}
module.exports.pitch = function () {
console.log('pitch 1')
}
- 运行测试
- 可以看出
webpack
会先从上往下、从左往右,依次执行pitch
,然后再从下往上、从右往左,依次执行loader
异步 loader
- 使用
this.async()
// loader2.js
module.exports = function (content) {
console.log('loader 2')
const callback = this.async()
setTimeout(()=>{
// callback 执行后,loader 才会继续向下执行
callback(null, content) // 参数分别是 错误信息、向下传递的内容
}, 1000)
}
- 运行测试
获取Options
- 配置
options
const path = require('path')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /.js$/,
use: [
'loader1',
'loader2',
{
loader: 'loader3',
// 配置 options
options: {
name: 'aa',
age: 17
}
}
]
}
]
},
resolveLoader: {
...
}
}
- 获取
options
// loader3.js
// loader-utils 由 webpack 提供
const { getOptions } = require('loader-utils')
module.exports = function (content) {
console.log('loader 3')
// 传入 this 并调用
const options = getOptions(this)
console.log(options)
return content
}
- 运行测试
校验 Options
- 制定校验规则
// loaders/scheme.json
{
"type": "object", // options 的类型
"properties": { // 可以配置的属性
"name": {
"type": "string",
"description": "姓名"
},
"age": {
"type": "number",
"description": "性别"
}
},
"additionalProperties": true // 是否可以配置额外属性
}
- 使用校验规则
// loader3.js
const { getOptions } = require('loader-utils')
// 引入并取出 validate
const { validate } = require('schema-utils')
// 读取校验规则
const schema = require('./scheme.json')
module.exports = function (content) {
console.log('loader 3')
const options = getOptions(this)
// 验证
// 校验规则、校验内容、loader的名字
validate(schema, options, {name: 'loader3'})
return content
}
- 运行测试:故意出现类型错误,如
age: "17"