H5W3
当前位置:H5W3 > JavaScript > 正文

稳定实战公式《幸运飞艇五码赚钱技巧规律》个人稳赚经验分享大家

【σσ:374441771 】计划群856082专业团队,专业导师精准计划!!!稳定收益,稳定回血!!
webpack提倡一切皆模块,所有类型的文件都可以经过文件加载器处理变成我们可加载的模块,那么这个文件加载器便是loader。

那么我们如何开发一个webpack loader呢,让我们一起探索探索吧~

一、loader执行顺序
在开发loader之前,我们先了解一下webpack loader的执行顺序。

webpack是支持loader的链式调用的,即一个文件可以经多个loader处理。当一个文件使用多个loader处理时,他的处理顺序是倒序,即传入loader数组的从右到左执行。

例如,对于scss文件,我们的配置如下,那么它的执行顺序是sass-loader -》 css-loader -》 postcss-loader -》style-loader:

module: {
rules: [
{
test: /.scss|.css/,
use: [
‘style-loader’,
{
loader: ‘css-loader’,
options: {
importLoaders: 2,
},
},
‘postcss-loader’,
loader: ‘sass-loader’,
],
}
}
二、loader开发
那么如何来开发一个loader呢?让我们慢慢来揭开webpack loader 的什么面纱~

loader其实是一个导出为函数的 JavaScript模块,是不是看起来很简单?实际呢,loader开发也很简单。即

test.loader.js内容如下:

module.exports = function(content) {
return transform(content); // 对content进行处理并返回给webpack
}
1、loader的传入参数
既然我们说了所谓 loader 只是一个导出为函数的 JavaScript模块,那么它的传入是什么呢?

content: string | Buffer, // 文件内容
sourceMap?: SourceMap, // 上一个loader解析完后生成的 source map
meta?: any // 会被 webpack 忽略,可以是任何东西(例如一些元数据)
显然loader就是对文件进行处理的,那么这里的content便是文件内容。

默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 raw,loader 可以接收原始的 Buffer。我们常用的file-loader就设置了raw为true,以告诉webpack传入原始的二进制数据

module.exports.raw = true;
需要注意的是:第一个 loader 的传入参数只有一个:资源文件的内容content。其他都是经过loader处理后可选择传递给下一个loader的。

2、loader处理结果
loader返回的处理结果应该和传入一样是 String 或者 Buffer。 上面有讲到除了content,loader其实还接受两个可选的入参,返回也一样。所以当我们如果是单个处理结果,可以在函数中直接返回。但是如果有多个处理结果,我们则必须通过this.callback()将处理结果传递给下一个loader。

module.exports = function(content) {
const newContent = transform(content); // 对content进行处理
this.callback(null,newContent, sourceMaps, meta);
return; // 当使用this.callback时函数应该return undefined
}
这里的this既不是webpack实例,也不是compiler、compilation、normalModule等这些实例。而是loader-runner构造的loaderContext对象,提供了各种loader API(具体API可见 https://webpack.js.org/api/loaders/ )。

对于meta参数,一般传入抽象语法树(abstract syntax tree – AST),这样可以在多个 loader 之间共享通用的 AST,这样做有助于加速编译时间。

所以总结来说,loader的工作流程是:

最后的 loader 最早调用,将会传入原始资源内容。
第一个 loader 最后调用,期望值是传出 JavaScript和 source map(可选)。
中间的 loader 执行时,会传入前一个 loader 传出的结果。
3、获取用户自定义参数
到这里基本已经清楚了loader的整个工作流程。我们在使用loader时,经常会传入一些自定义的options,那么loader怎么获取这些options呢?

webpack 提供了loader-utils包和schema-utils 包。loader-utils提供了许多有用的工具,但最常用的一种工具是获取传递给 loader 的选项。schema-utils 包配合 loader-utils,用于保证 loader 选项,进行与 JSON Schema 结构一致的校验。

const loaderUtils = ‘loader-utils’;
module.exports = function(content) {
const options = loaderUtils.getOptions(this); // 用户传入的options
return transform(content); // 对content进行处理并返回给webpack
}
4、控制loader执行
前面讲到过,webpack的loader执行顺序是从后往前。有些时候我们希望选择性的越过后续loader执行,webpack给每个loader提供了pitch方法进行设置。

根据webpack官网给出的案例,对于下面的配置:

module.exports = {
//…
module: {
rules: [
{
//…
use: [
‘a-loader’,
‘b-loader’,
‘c-loader’
]
}
]
}
};
webpack 在实际(从右到左)执行 loader 之前,会先从左到右调用 loader 上的 pitch 方法。所以实际执行顺序如下:

|- a-loader pitch
|- b-loader pitch
|- c-loader pitch
|- requested module is picked up as a dependency
|- c-loader normal execution
|- b-loader normal execution
|- a-loader normal execution
pitch方法若有返回值,则会跳过后续的loader。比如上面如果 b-loader 的 pitch 方法有返回值,那么此时loader的执行流程是:

|- a-loader pitch
|- b-loader pitch returns a module
|- a-loader normal execution
三、举个栗子
接下来我们来开发一个自己的loader

比如现在有个场景,要求我们给所有的apng 请求url加上参数?nowebp=1。loader代码如下:

apng-url-resolve.js

module.exports = function(content) {
return content.replace(/.apng(.*.png)?/, ‘.apng$1?nowebp=1’)
}
webpack loader 配置:

const path = require(‘path’);
modules:
{
rules: [
{
test: /.js$/
use: path.resolve(__dirname, ‘build/loaders/apng-url-resolve.js’ )
}
]
}

本文地址:H5W3 » 稳定实战公式《幸运飞艇五码赚钱技巧规律》个人稳赚经验分享大家

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址