参考 :译文 编写一个loader

https://webpack.github.io/docs/loaders.html

按照loader的返回值可以分为两种:

  • 最左loader:这种loader会返回字符串描述的js模块代码,已经是loader的最终处理结果了,这样的字符串会被添加到webpack的模块函数中
  • 非最左loader:返回值不是js模块代码,而仅仅是对资源的中间处理结果,这样的字符串需要被后续的loader处理

一般情况下,在loader的链式调用中,一般是这样:最左loader!非最左loader!非最左loader ....

简单loader例子

// loaders/myLoader.js 返回的值是js模块代码,这个loader属于最左loader
module.exports = function loader(source) {
return `module.exports = {fn: ${source}}`;
}; // main.js
const src = require("./src")
src.fn(); // src.js
alert(999) //配置文件
const path = require('path')
module.exports = {
entry: [__dirname + "/main.js"],
output: {
path: __dirname + "/dist",
filename: "bundle.js",
},
module: {
loaders:[
{
test: /src.js/,
use: [
{
loader: path.resolve(__dirname, './loaders/myLoader.js'),
}
]
}
]
}
}

打包后的结果

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) { const src = __webpack_require__(2)
src.fn(); /***/ }),
/* 2 */
/***/ (function(module, exports) { module.exports = {fn: alert(999)} /***/ })
/******/ ]);

注意:如果loader处理的是所有js,则入口文件是js的话也会被处理。

从以上代码可以看出,对于某些loader,他们导出的结果可能并不重要,而是可以在导出之前,根据拿到的文本内容对页面做一些操作。

aync loader

把以上小例子中的loader定义为:

module.exports = function(source) {
var callback = this.async();
setTimeout(function(){
callback(null,`module.exports = {fn: ${source}}`)
},5000);
};

启动打包后,经过5s才打包完成。打包结果和以上小例子中的一致。

pitching loader

  在loader函数对象上添加一个pitch属性,这个pitch所执行的函数称为pitching loader。在pitching loader中可以通过data把数据传递给对应的loader,而不能传递给其他loader。

  在链式调用中,pitching loader 与 loader的执行次序(以 a!b!c!resource 为例):

  • pitch a

    • pitch b

      • pitch c

        • read file resource (adds resource to dependencies)
      • run c
    • run b
  • run a

  在pitching loader有返回值时的情况

  • pitch a

    • pitch b (returns something)
  • run a

  可见,哪个pitching loader有返回值,则对应的loader以及后续的loader都不执行了。以上例子中a loader函数的第一个参数就是b pitching loader的返回值。

pitching loader的应用场景

  问题是有时候我们想把两个第一种loader chain起来,比如

style-loader!css-loader

  而 css-loader的返回值是一串js代码(包含了module.export=xxx这样的字符串),如果按正常方式写style-loader的参数就是一串代码字符串。就算eval了也不一定拿到什么值:

eval('module.export="result";console.log("hello world")') === "hello world"

  为了解决这种问题,我们需要在style-loader里执行require(css-loader!resouce), 这会把css-loader跑一遍,也就是说如果按正常顺序执行css-loader会跑两遍(第一遍拿到的js代码用不了), 为了只执行一次,style-loader利用了pitching, 在pitching函数里require(css-loader!resouce)。然后返回js代码(style-loader能够作为最左边loader)

  

自定义loader基础知识的更多相关文章

  1. Java自定义注解基础知识

    注解分为三类:没有任何元素的注解,有一个元素的注解和有多个元素的注解. 1. Marker注解 这类注解没有任何元素,此类注解仅仅是一个标示.如下所示: public @interface Good ...

  2. ASP.NET基础知识汇总之WebConfig自定义节点详细介绍

    之前介绍过Webconfig的具体知识ASP.NET基础知识汇总之WebConfig各节点介绍.今天准备封装一个ConfigHelper类,涉及到了自定义节点的东东,平时虽然一直用,但也没有系统的总结 ...

  3. php面试笔记(5)-php基础知识-自定义函数及内部函数考点

    本文是根据慕课网Jason老师的课程进行的PHP面试知识点总结和升华,如有侵权请联系我进行删除,email:guoyugygy@163.com 在面试中,考官往往喜欢基础扎实的面试者,而函数相关的考点 ...

  4. TestStand 基础知识[7]--Build-in Step Types (2)

    接着上一篇文章:TestStand 基础知识[6] Build-In StepTypes(1) 继续介绍: 还是先把Build-in StepTypes图片贴一下, 1. Call Executabl ...

  5. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  6. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  7. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  8. 学习 shell脚本之前的基础知识

    转载自:http://www.92csz.com/study/linux/12.htm  学习 shell脚本之前的基础知识 日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写sh ...

  9. 基础知识《十》unchecked异常和checked异常

    运行时异常在运行期间才能被检查出来,一般运行期异常不需要处理.也称为unchecked异常.Checked异常在编译时就能确定,Checked异常需要自己处理. checked 异常也就是我们经常遇到 ...

随机推荐

  1. 浏览器启动android应用

    window.location.href = "xl://com.caho.app:8888/app?name=chao"; <activity> <intent ...

  2. 3.KPCR

    KPCR: CPU控制区(Processor Control Region) 当线程进入0环时, FS:[0]指向KPCR(3环时FS[0]-> TEB)每个CPU都有一个KPCR结构体(一个核 ...

  3. Testing Complex Logic with JMeter Beanshell

    BeanShell是最先进的JMeter内置组件之一.JMeter具有丰富的内置插件,可满足性能测试的许多需求.例如,在编写一些复杂的测试时,您可能需要一些额外的脚本.在这种情况下,值得使用Beans ...

  4. scrapy框架中Item Pipeline用法

    scrapy框架中item pipeline用法 当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的pyt ...

  5. GYM 101673J(模拟)

    本来我就模拟和搜索恐惧症,场上乍一看调度来调度去的真的吓得没敢写.然鹅赛后听说别的队写得贼短就写了写,真的不难--嘤嘤嘤 #include <cstdio> #include <cs ...

  6. 防止a标签跳转的几种方法

    第一种方法 在a标签的href中添加属性值 <a href="javascript:void(0)"></a> 第二种方法 给a标签添加点击事件,函数的返回 ...

  7. mongodb的基本命令操作

    mongodb在已经存在管理员的情况下,需要创建一个库 使用管理员进入mongodb的命令行界面 mongo admin -u 管理员名 -p 管理员密码 创建库(进入库) use 库名 创建当前库的 ...

  8. 剑指 Offer

    3.1 找出数组中重复的数 来源:AcWing 题目描述 给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内. 数组中某些数字是重复的,但不知道有几个数字重复了,也不 ...

  9. HDU4576 Robot(概率)

    题意 抄袭自https://www.cnblogs.com/Paul-Guderian/p/7624039.html  多组输入n,m,l,r.表示在一个环上有n个格子.接下来输入m个w表示连续的一段 ...

  10. FPGA的嵌入式RAM

    FPGA中的嵌入式RAM分为两种:专用的BRAM和分布是RAM(用LUT实现的).这两种RAM又可以配置成单端口和双端口的RAM和ROM.双端口RAM又可以根据读写地址是否在同一块分为Double P ...