分类

loader 分成哪几类?如果指定类型?

loader 的叠加顺序 = post(后置)+inline(内联)+normal(正常)+pre(前置)。Rule.enforce 可能的值有:"pre" | "post",指定 loader 种类。没有值表示是普通 loader。还有一个额外的种类"行内 loader",loader 被应用在 import/require 行内。

module: {rules: [{test: /\.css$/,use: [// 直接这样配置就是normal'css-loader']},{test: /\.css$/,enforce: 'pre',use: [// 这样是前置pre'style-loader']},{test: /\.less$/,enforce: 'post',use: [// 这样是后置post'less-loader']}]
}
// 这样是内联inline
import Styles from 'style-loader!css-loader?modules!./styles.css';

特殊配置

加载模块前的特殊符号是如何工作的?

符号 变量 含义
-! noPreAutoLoaders 不要前置和普通 loader
! noAutoLoaders 不要普通loader
!! noPrePostAutoLoaders 不要前后置和普通 loader,只要内联 loader

内联方式,可以在 import 语句或任何 与 "import" 方法同等的引用方式 中指定 loader。使用 ! 将资源中的 loader 分开。每个部分都会相对于当前目录解析。

import Styles from 'style-loader!css-loader?modules!./styles.css';

通过为内联 import 语句添加前缀,可以覆盖 配置 中的所有 loader, preLoader 和 postLoader:

使用 ! 前缀,将禁用所有已配置的 normal loader(普通 loader)

import Styles from '!style-loader!css-loader?modules!./styles.css';

使用 !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)

import Styles from '!!style-loader!css-loader?modules!./styles.css';

使用 -! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders

import Styles from '-!style-loader!css-loader?modules!./styles.css';

选项可以传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}

组合

这些不同的loader是如何组合的?

还有一个额外的种类"行内 loader",loader 被应用在 import/require 行内。

所有一个接一个地进入的 loader,都有两个阶段:

1、Pitching 阶段: loader 上的 pitch 方法,按照 后置(post)、行内(inline)、普通(normal)、前置(pre) 的顺序调用。

2、Normal 阶段: loader 上的 常规方法,按照 前置(pre)、普通(normal)、行内(inline)、后置(post) 的顺序调用。模块源码的转换, 发生在这个阶段。

loader 总是 从右到左被调用。有些情况下,loader 只关心 request 后面的 元数据(metadata),并且忽略前一个 loader 的结果。在实际(从右到左)执行 loader 之前,会先 从左到右 调用 loader 上的 pitch 方法。

loader 可以通过 request 添加或者禁用内联前缀,这将影响到 pitch 和执行的顺序。

对于以下 use 配置:

module.exports = {//...module: {rules: [{//...use: ['a-loader', 'b-loader', 'c-loader'],},],},
};

将会发生这些步骤:

|- 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

那么,为什么 loader 可以利用 "pitching" 阶段呢?

首先,传递给 pitch 方法的 data,在执行阶段也会暴露在 this.data 之下,并且可以用于在循环时,捕获并共享前面的信息。

module.exports = function (content) {return someSyncOperation(content, this.data.value);
};module.exports.pitch = function (remainingRequest, precedingRequest, data) {data.value = 42;
};

其次,如果某个 loader 在 pitch 方法中给出一个结果,那么这个过程会回过身来,并跳过剩下的 loader。在我们上面的例子中,如果 b-loader 的 pitch 方法返回了一些东西:

module.exports = function (content) {return someSyncOperation(content);
};module.exports.pitch = function (remainingRequest, precedingRequest, data) {if (someCondition()) {return ('module.exports = require(' +JSON.stringify('-!' + remainingRequest) +');');}
};

上面的步骤将被缩短为:

|- a-loader `pitch`|- b-loader `pitch` returns a module
|- a-loader normal execution

loader-runner

所谓 loader 只是一个导出为函数的 JavaScript 模块。它接收上一个 loader 产生的结果或者资源文件(resource file)作为入参。也可以用多个 loader 函数组成 loader chain。compiler 需要得到最后一个 loader 产生的处理结果。这个处理结果应该是 String 或者 Buffer(被转换为一个 string)。loader-runner 是一个执行 loader chain 的模块。

const { runLoaders } = require("loader-runner")
const fs = require("fs")runLoaders({resource: "/Users/didi/workspace/2021/webpack5/source.js?query", // 你要加载的资源loaders: ["/Users/didi/workspace/2021/webpack5/loader.js?query"], // 需要处理的loadercontext: { minimize: true }, // 保存一些状态和值readResource: fs.readFile.bind(fs)
}, function(err, result) {console.log(err, '运行错误')console.log(result, '运行结果')
})

经过 loader-runner 处理的结果为:

{result: [ "console.log('hello world')// hello world" ],resourceBuffer: <Buffer 63 6f 6e 73 6f 6c 65 2e 6c 6f 67 28 27 68 65 6c 6c 6f 20 77 6f 72 6c 64 27 29>,cacheable: true,fileDependencies: [ '/Users/didi/workspace/2021/webpack5/source.js' ],contextDependencies: [],missingDependencies: []
}

理解 loader 的工作流相关推荐

  1. 深入理解学习Git工作流

    2019独角兽企业重金招聘Python工程师标准>>> 个人在学习git工作流的过程中,从原有的 SVN 模式很难完全理解git的协作模式,直到有一天我看到了下面的文章,好多遗留在心 ...

  2. 深入理解python.md_深入理解学习Git工作流(git-workflow-tutorial)

    个人在学习git工作流的过程中,从原有的 SVN 模式很难完全理解git的协作模式,直到有一天我看到了下面的文章,好多遗留在心中的困惑迎刃而解,于是我将这部分资料进行整理放到了github上,欢迎st ...

  3. 工作流系统理解(1)

    分成 工作流建模 工作流引擎 工作流系统,根据个人理解,通过工作流建模工具进行工作流的模型建立,定义好XDPL文件,工作流引擎根据XDPL定义文件进行解释执行,完成工作流的各种任务.工作流建模系统应该 ...

  4. 为什么使用 Git-flow 工作流

    该内容由联想乐窗团队张敬佩整理 内容摘自网上,如有侵权,联系删除 Git-flow 工作流介绍 主要内容 本文主要分主要包括以下几个部分的内容 集中式工作流 功能分支工作流 功能分支工作流的问题 gi ...

  5. JBPM工作流引擎内核设计思想及构架

    1 前言 流程引擎内核仅是"满足Process基本运行"的最微小结构,而整个引擎则要复杂很多,包括"状态存储"."事件处理"."组 ...

  6. 实现一下几个简单的loader

    文章目录 一 关于loader 1.理解 2.分类 1.同步loader 2.异步loader 3.raw loader 4.pitch loader 二.自己实现一些loader 一.clean-l ...

  7. web工作流管理系统开发之一 工作流概念

    曾经在2001年做CRM产品的时候,因为CRM产品的客户状态升迁,每个具体用户的升迁规则可能会不一样,技术主管说要集成一个工作流软件工具......,那是我第一次听说工作流.当时很不理解,这工作流软件 ...

  8. Activiti工作流浅析

    新钛云服已累计为您分享695篇技术干货 一.工作流 1.工作流概述 在一个公司业务中,每一个业务的开始和结束,都可以理解成为一个工作流.例如公司请假的基本流程. 如图所示,员工先提出请假申请,提交该申 ...

  9. 一、Camunda工作流的学习路线(开局一把刀,学完后青铜变王者)

    前言 我写这篇文章的目的是为了将camunda工作流的相关知识系统化,目前网上的文章知识点很散,有些文章也不适合目前的企业级项目开发. 学习路线: 一.如果你是小白,你需要自己去理解什么是工作流?其作 ...

最新文章

  1. 代码的演化-DI(理解依赖注入di,控制反转ioc)
  2. hashmap允许null键和值吗_hashMap底层源码浅析
  3. SQL Server2005重装Performance Monitor Counter 的问题解决
  4. 【联盛德W806上手笔记】五、TIM定时器
  5. android 瀑布流效果 保存地址
  6. MS SQL 数据库状态为SUSPECT的处理方法
  7. 《Java安全编码标准》一导读
  8. 红包随机分配问题php,自己写仿微信红包的随机分配,为什么平均数差距这么大?...
  9. 毕设项目 - 基于SSM的音乐网站(含源码+论文)
  10. PTAM的笔记(二)---ptam移植到android平台
  11. 阵列卡PERCH330_H730配置手册
  12. 语言模型(language model)
  13. 3. Kubernetes资源-概述
  14. 命令点亮硬盘灯_【硬盘无法识别怎么办?】
  15. 前端利用正则对手机号码,身份证号,姓名进行脱敏处理
  16. 中南大学计算机基础在线作业答案三,中南大学计算机基础三答案.doc
  17. 【随笔】方波的表示、转换与应用
  18. 2023年提高Google关键词排名的方法,如何提高谷歌排名?
  19. UML系列文章(23)高级行为---进程和线程
  20. 西雅图,夜未眠 2008-06-27

热门文章

  1. 保证MQ消费消息的幂等性,真可以用版本号的方式?
  2. 阿里工程师教你 3 分钟实现数据源编排和接入
  3. 如何高效地远程部署?Fabric 来支招!
  4. 千亿市场空间开启!网络安全开启新纪元步入黄金时代
  5. 程序员躲不掉的“中年危机”
  6. 图灵奖得主 Bengio:深度学习不会被取代!
  7. 阿里云张建锋:工业互联网不是工业自动化
  8. C/C++ 最易受攻击、70% 漏洞无效,揭秘全球开源组件安全现状
  9. DOS 入侵、群发邮件、心脏起搏器……病毒攻击简史!
  10. 程序员的代码写的再牛也没有马伊琍文章的分手语牛!