探秘 webpack 中 loader 的实现方式

正值前端组件化开发时代,那么必然离不开目前最火的构建工具——webpack(grunt,gulp等暂且不谈)。说到这里,刚好有几个问题:
  • 为什么运行打包命令之后,.vue 文件可以转成 .js 文件
  • 为什么运行打包命令之后,.less 文件可以转成 .css 文件
  • 为什么运行打包命令之后,ES6+ 语法可以转成 ES5 语法

上面这几个问题,就引出了我们的主角——【loader】。
loaderwebpack 的一块很重要的组成部分。我们都知道 webpack 是用于资源打包的,里面的所有资源都是“模块”,内部实现了对模块资源进行加载的机制。但是 Webpack 本身只能处理 js 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。 Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接收文件源码作为参数,返回转换的结果,例如可以使用 loader 加载器可以快速编译预处理器 (less,sass,coffeeScript)Loader 可以在 require() 引用模块的时候添加,也可以在 webpack 全局配置中进行绑定,还可以通过命令行的方式使用。(本篇中的参数配置及使用方式均基于 webpack4.0 版本)

一、loader的特点

1、loader 的执行顺序和代码书写的顺序是相反的,即:从下至上,从右至左。
2、第一个执行的 loader 会接收源文件做为参数,下一次执行的 loader 会接收前一个 loader 执行的返回值做为参数
3、需要严格遵循“单一职责”原则,即每个 loader 只负责自己需要负责的事情

二、loader API

methods 含义
this.request 被解析出来的 request 字符串。例子:"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"
this.loaders 所有 loader 组成的数组。它在 pitch 阶段的时候是可以写入的。
this.loaderIndex 当前 loader 在 loader 数组中的索引。
this.async 告诉 loader-runner 这个 loader 将会异步地回调
this.callback 一个可以同步或者异步调用的可以返回多个结果的函数
this.data 在 pitch 阶段和正常阶段之间共享的 data 对象。
this.cacheable 设置是否可缓存标志的函数
this.resource request 中的资源部分,包括 query 参数
this.resourcePath 资源文件的路径。
this.resourceQuery 资源的 query 参数
this.target 编译的目标。从配置选项中传递过来的。
this.webpack 如果是由 webpack 编译的,这个布尔值会被设置为真
this.sourceMap 应该生成一个 source map。因为生成 source map 可能会非常耗时,你应该确认 source map 确实有必要请求。
this.emitWarning 发出一个警告。
this.emitError 发出一个错误。
this.loadModule 解析给定的 request 到一个模块,应用所有配置的 loader ,并且在回调函数中传入生成的 source 、sourceMap 和 模块实例(通常是 NormalModule 的一个实例)。如果你需要获取其他模块的源代码来生成结果的话,你可以使用这个函数。
this.resolve 像 require 表达式一样解析一个 request 。
this.emitFile 产生一个文件。这是 webpack 特有的。
this.fs 用于访问 compilation 的 inputFileSystem 属性。
this.value 向下一个 loader 传值。如果你知道了作为模块执行后的结果,请在这里赋值(以单元素数组的形式)。
this.inputValue 从上一个 loader 那里传递过来的值。如果你会以模块的方式处理输入参数,建议预先读入这个变量(为了性能因素)。
更多详细API,以及各API的用法示例,可以访问官网查看。地址:https://www.webpackjs.com/api/loaders

三、写loader之前的需求整理

现在有这样一个需求,使用 hxkj-loader 加载并处理名称为 *.hxkj.vip 的文件,将里面的哈希空间全部替换为 www.hxkj.vip。需要实现的转换如下:

转换前的内容:

<div>
    <h1>欢迎访问哈希空间</h1>
    <p>哎哟,终于等到你。这里就是让人流连忘返的哈希空间呀!</p>
</div>

转换后的内容:

<div>
    <h1>欢迎访问www.hxkj.vip</h1>
    <p>哎哟,终于等到你。这里就是让人流连忘返的www.hxkj.vip呀!</p>
</div>

四、编写loader

在与 webpack.config.js 同级目录下新建 hxkj-loader.js,文件的内容如下:

module.exports = function(source){
    var content="";
    content = source.replace("/哈希空间/g","www.hxkj.vip");
    return content; 
}

接下来,需要在 webpack.config.js 文件中增加以下的配置:

const path = require("path"); // 引入 node 的 path 模块
...
module:{
    rules:[{
        test: /\.hxkj\.vip$/, // 正则匹配以 hxkj.vip 结尾的文件
        use:[{
            loader:path.resolve(__dirname, "hxkj-loader") // 使用 path 模块找到 hxkj-loader 的路径
        }]
    }]
}
好,到此,一个简易版的 loader 就已经写完了。目前 loader 是直接写在本地的,可以考虑将自己写好的 loader 发布到 npm,这样就更加完善了。

At last,看完之后有什么不懂的,可以留言反馈。

转载请注明出处:https://www.jianshu.com/p/51b793f6fa0e
作者:TSY
个人空间:https://hxkj.vip

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350