跳到主要内容

认识

2024年04月06日
柏拉文
越努力,越幸运

一、认识


Webpack 中的 loader 本质上是一个函数, 接收文件内容源代码作为入参, 同时返回处理后的结果。

Webpackloader-runner 核心逻辑为: 在 Webpack 进入构建阶段后,首先接受待处理的资源文件路径, 会通过 IO 接口读取文件内容,之后调用 LoaderRunner 并将文件内容以 source 参数形式传递到 Loader 数组,source 数据在 Loader 数组内首先经过pitch阶段读取资源文件内容再经过normal阶段处理资源文件内容,最终以标准 JavaScript 代码提交给 Webpack 主流程,以此实现内容翻译功能。

二、类型


2.1 inline loader

2.2 pre loader

2.3 normal loader

2.4 post loader

三、执行


loader 的执行阶段实际上分为两个阶段,webpack在使用loader处理资源时首先会经过loader.pitch阶段,pitch阶段结束后,读取资源文件, 将读取的资源文件内容交给 normal 阶段处理。

  1. Pitching 阶段: loader 上的 pitch 方法,按照 后置(post)、行内(inline)、普通(normal)、前置(pre) 的顺序调用。任意一个loaderpitch函数如果返回了非undefined的任何值,会发生熔断效果, 不会读取资源文件内容, 直接将pitch的返回值传递给normal阶段loader的函数。

  2. Normal 阶段: loader 上的 常规方法,按照 前置(pre)、普通(normal)、行内(inline)、后置(post) 的顺序调用。loader函数的返回值会在loader chain中进行一层一层传递直到最后一个loader处理后传递将返回值给webpack进行传递。需要额外注意的是,在normal阶段的最后一个loader一定需要返回一个js代码(一个module的代码,比如包含module.exports语句)

示例如下:

// webpack.config.js

module.exports = {
module: {
rules: [
// 普通loader
{
test: /\.js$/,
use: ['normal1-loader', 'normal2-loader'],
},
// 前置loader
{
test: /\.js$/,
use: ['pre1-loader', 'pre2-loader'],
enforce: 'pre',
},
// 后置loader
{
test: /\.js$/,
use: ['post1-loader', 'post2-loader'],
enforce: 'post',
},
],
},
};

// 入口文件中
import something from 'inline1-loader!inline2-loader!./title.js';

loader的执行顺序:

Preview

纯函数.pitch 如果返回一个非 undefined 的值会发生熔断。 loader 执行链条会被阻断, 立马掉头执行, 直接掉头执行上一个已经执行的loadernormal阶段并且将pitch的返回值传递给下一个normal loader。如下图所示:

Preview

四、细节


4.1 runLoader

function runLoader(options,callback){

}
  • options:

    • resource: 表示需要加载的资源路径

    • loaders: 表示需要处理的loader绝对路径拼接成为的字符串,以!分割

    • context: loader上下文对象,webpack会在进入loader前创建一系列属性挂载在一个object上,而后传递给loader内部。

    • processResource: 读取资源文件的方法

  • callback

参考资料


多角度解析Webpack5之Loader核心原理

你不知道的「pitch loader」应用场景