webpack loader 核心机制分析
什么是loader?
loader 是一个函数,通过它我们可以在 webpack 处理特定资源(文件)之前,对资源进行预处理,比如:webpack 仅仅只能够识别 js
模块,而我们在使用 ts 编写代码的时候可以提前通过 babel-loader 将 .ts 为后缀的文件编译成 .js 文件,这样 webpack 就可以识别了。
常用配置参数
基础配置示例
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: 'css-loader',
enforce: 'post'
},
{
test: /.ts$/,
use: 'ts-loader'
}
]
}
}
// 注意,use的值是一个数组,数组的执行顺序是从右往左,从下往上;
testreg表示的是匹配规则,可以是正则表达式,也可以是字符串,也可以是数组usestring|string[]表示的是test中匹配到的文件应该使用哪一个loader处理,enforcepre: 前置执行;post: 后置执行
例如:
module.exports = {
module: {
rules: [
{test: /.css$/, use: 'sass-loader', enforce: 'pre'},
{test: /.css$/, use: 'css-loader'},
{test: /.css$/, use: 'style-loader', enforce: 'post'},
]
}
}
执行顺序为
graph LR
A[sass-loader] --> B[css-loader] --> C[style-loader]
loader 的执行顺序为
graph LR
A[pre-loader] --> B[normal-loader] --> C[inline-loader] --> D[post-loader]
pitch 阶段的执行顺序
pitch 阶段的说明
loader 的执行阶段分为两个阶段
webpack在使用loader处理资源时,首先会经过loader.pitch阶段pitch阶段结束后才会读取文件,在之后才会进行normal阶段的处理
Pitch 阶段:loader 上的 pitch 方法,按照 后置(post)-> 行内(inline)->普通(normal)->前置(pre)->的顺序调用;
Norma 阶段:loader 上的常规方法,按照 前置(pre)->普通(normal)->行内(inline)->后置(post)的顺序调用。
function loader() {
// 正常的loader 执行阶段...
}
// remainingRequest:表示剩余需要处理的loader 的绝对路径,以! 分割组成的字符串
// precedingRequest:表示pitch 阶段已经迭代过的loader, 按照 ! 分割成的字符串;
// data : 在pitch 和 loader之间交互的数据
loader.pitch = function (remainingRequest, precedingRequest, data) {
// pitch loader
// 如果return 了一个非 undefined 的值,会带来 【熔断效果】
}
inline loader 举例
- ! 前缀, 将禁用所有已经配置的
normal loader
import Styles from '!style-loader!css-loader?modules!./style.css';
- !! 前缀, 将禁用所有已经配置的 loader (
pre loader,normal loader,post loader)
import Styles from '!!style-loader!css-loader?modules!./style.css';
- -! 前缀, 将禁用所有已经配置的
pre loader和loader, 但是不禁用post loader
import Styles from '-!style-loader!css-loader?modules!./style.css';
loader 的种类
同步 loader
module.exports = function (content) {
return someSyncOperation(content);
}
异步 loader
function asyncLoader() {
return Promise((resolve) => {
resolve('this is result value')
})
}
function asyncLoader() {
const callback = this.async();
// do something
callback('this is result value')
}
raw loader
默认情况下,资源文件会被转化成 UTF-8字符串,然后传给 loader。 通过谁知 raw, loader 可以接受原始的 Buffer。 每一个loader
都可以使用 string 或者 buffer 的形式传递它的处理结果。 Compiler 将会把他们在 loader 之间相互转换