【javascript】手写一个webpack loder

手写一个loader

为什么需要loader?

 webpack 实际上只能处理js文件,那么对于除了js文件的其他类型的文件 比如 css sass 等。。我们不能直接用webpack来处理。

 我们需要一个翻译员(loader)来帮我们的文件处理一下。有时候我们不只需要一个翻译员来工作,比如要把文言文翻译成外语,首先要转换成白话文,然后转换为外语。

 Loader就像一个翻译员,能将源文件经过转化后输出新的结果,并且一个文件还可以链式的经过多个翻译员翻译。

以scss文件为例:

 先将scss源代码交给sass-loader,将scss转换成css;
 将sass-loader输出的css提交给css-loader处理,找出css中依赖的资源,压缩css;
 将css-loader输出的css提交给style-loader处理,转换成通过脚本加载的javascript代码。

 最终的结果一定是javascript代码。

编写loader的原则

  职责单一: 一个loader只做一件事情。优点:容易维护且能够链式调用
  模块化:
保证输出模块化,loader生成的模块与普通块遵循的相同的设计原则
  无状态:
确保loader在不同模块转换之间,不保存状态。每次运行都应该独立于其他编译模块以及相同模块之前的编译结果。

动手写一个基础loader

 webpack运行在Node上,一个loader其实就是一个node模块,这个模块需要导出一个函数。这个导出的函数输入的就是处理前的原内容,对内容处理之后 然后输出被处理过的内容。

我们现在写一个简单的javascript loader,这个loader的作用就是将js文件内容里面的字符串 like 转换成 ❤ 。

直接上代码,我们将这个loader命名为k-loader.js

module.exports = function (source) {const regExp = new RegExp("like", "ig")const result = source.replace(regExp, "❤")return result
}

怎么调试我们的loader,我们使用官方推荐的一种:

module.exports = {module: {rules: [{test: /\.js$/,use: [{loader: path.resolve('path/to/loader.js'),options: {/* ... */}}]}]}
};

 定义好loader然后找到该loader相对于webpack配置文件的路径即可。
 我们看k-loader.js 做了什么,获取到source,source就是加载的js文件的文件内容,然后做了一次数据清洗,将like全部转换成❤,然后返回字符串。 完事儿!这就ok了,你可以做一个测试,你会发现js文件里面的like全部被替换成了❤,是不是很简单。。是的。

基础loader上增加一些配置

 我们一般的loader是有option配置的,就是说用户需要自定义一些功能。
我们把这个like 和 ❤,配置在option里面,这样的话,就可以灵活的使用了,我们只需要改like 和 ❤的值即可。我们使用到了webpack提供的辅助模块loder-util,我们通过getOPtions(this)方法可以获取到webpack配置loader的时候传递的option值。
代码长这样:

const loaderUtils = require("loader-utils")module.exports = function (source) {const options = loaderUtils.getOptions(this) || {}// 假定option只有一个key value// 这里应该对option做一次验证。const key = Object.keys(options)[0]const value = options[key]const regExp = new RegExp(key, "ig")const result = source.replace(regExp, value)return result
}

这样我们将options的值配置成{ like: "❤" }就会和我们上面的hard code 达到一样的效果,我们将options改成{like: "love"}这样就会把所有js文件里面的like替换成love。

到这一步,我们就已经可以自己编写一个loader了。


返回多个值

 我们上面写的loader只是返回了一个值,在一些特殊的场景我们需要用this.callback()返回多个值。

 以用babel-loader转换ES6代码为例,它需要输出转换后的ES5代码对应的SourceMap 以方便调试源码。 为了将Source Map也一起随着ES5代码返回给Webpack,还可以这样写:

module.exports = function(source) {this.callback(null, source, sourceMaps)return; // 当调用 callback() 时总是返回 undefined
}

this.callback API长下面的样子:

this.callback(err: Error | null,content: string | Buffer,sourceMap?: SourceMap,meta?: any
);

同步或异步

loader有同步和异步之分,这时候我们需要使用this.async()来获取callback函数。

module.exports = function(content, map, meta) {var callback = this.async();someAsyncOperation(content, function(err, result) {if (err) return callback(err);callback(null, result, map, meta);});
};

参考:

编写一个loader
loader-api

完整demo 见这里:

https://github.com/aeolusheath/webpack-certain-features/tree/master/write-loader-diy

好文要顶 关注我 收藏该文  

【javascript】手写一个webpack loder相关推荐

  1. 手写一个简易bundler打包工具带你了解Webpack原理

    用原生js手写一个简易的打包工具bundler

  2. 未能加载文件或程序集或它的某一个依赖项_手写一个miniwebpack

    前言 之前好友希望能介绍一下 webapck 相关的内容,所以最近花费了两个多月的准备,终于完成了 webapck 系列,它包括一下几部分: webapck 系列一:手写一个 JavaScript 打 ...

  3. 手写一个promise用法_手写一个 Promise

    1 js 的基本数据类型? 2 JavaScript 有几种类型的值? 3 什么是堆?什么是栈?它们之间有什么区别和联系? 4 内部属性 [Class] 是什么? 5 介绍 js 有哪些内置对象? 6 ...

  4. ES6 手写一个“辨色”小游戏

    1. 前言 依稀记得几年前朋友圈流行的辨色小游戏,找出颜色不同的矩形.前些天突发奇想,打算自己手写一个类似的游戏,话不多说,先上 Demo . --项目源码 本实例基于 ES6 实现,并兼容 ie9及 ...

  5. 分页器的使用-2 手写一个分页器

    有时候项目中要求分页器样式自定义时,就需要自己去手写一个分页器了,怎么做呢,直接上代码,具体详情已经在注释里写清楚了. 注意:1. currentPage.count.pageCount为全局变量2. ...

  6. 用 Node.js 手写一个 DNS 服务器

    DNS 是实现域名到 IP 转换的网络协议,当访问网页的时候,浏览器首先会通过 DNS 协议把域名转换为 IP,然后再向这个 IP 发送 HTTP 请求. DNS 是我们整天在用的协议,不知道大家是否 ...

  7. 用Java手写一个微型下载资源网站

    文章目录 手写一个微型下载资源网站[Java实现用户注册.登陆.下载功能] 一.技术栈 二.流程分析图 注册 登陆 下载 三.案例实现效果 首页 注册 登陆 下载网主页 壁纸下载 书籍下载 影视下载 ...

  8. 三分钟手写一个迷你jQuery,附源码

    诚然,不管前端技术怎么发展,重心都不会变,就是 操作DOM + 获取数据. 下面的代码演示了如何快速手写一个简单的jQuery: <!DOCTYPE html> <html lang ...

  9. 十五分钟用JavaScript基础写一个图片轮播效果

    十五分钟用JavaScript基础写一个图片轮播效果 前言 这次也是一个适合JavaScript初学者的小练手,用JavaScript的基本知识去写一个轮播图,其实轮播图有很多方法去实现,像用一些框架 ...

最新文章

  1. 树莓派做网站服务器同时做nas,【项目分享】树莓派4搭建NAS,让硬盘轻松联网...
  2. 漫谈“外来的和尚会念经”
  3. 浅谈基于软交换的下一代网络技术
  4. 源码分析--SDWebImage
  5. iso27001认证怎么申请?(iso27001认证基本条件和详细流程)
  6. dijikstra 旅行商问题_车辆路径问题与算法
  7. 软考网络工程师-华为设备命令学习笔记
  8. 【滤波器】基于matlab时变维纳滤波器设计【含Matlab源码 1870期】
  9. 飞桨day-03 人脸关键点检测实践作业
  10. 虚拟化性能计数器需要至少一个可正常使用的计数器。 模块“VPMC”启动失败。 未能启动虚拟机。
  11. tensorflow 如何计算向量余弦相似 cosine similarity
  12. 怎样快速查询单号物流信息,筛选出未签收的单号
  13. 信息与通信的数学基础——第十三章 行波法
  14. CVE-2018-12613 --- 本地文件包含造成远程代码执行漏洞复现
  15. 2022年资料员-岗位技能(资料员)操作证考试题模拟考试平台操作
  16. 喧喧发布 2.5.3 版本,主要提升系统稳定性,优化交互体验
  17. 在Python中如何方便的制作个性化的词云图
  18. flexray unknown message
  19. idead文件折叠问题终极解决办法
  20. 图书推荐系统(附源码链接)

热门文章

  1. Fisher Discriminant
  2. 伤心是每个故事最最无奈的结局
  3. 【金融】券商研究所策略组的市场行情判断和行业配置有效吗——基于几组回测的结果证明(大大地有效!!)
  4. Realsense T265双目+IMU传感器追踪相机的环境配置指南(Ubuntu+Windows)
  5. C++设计一个Bank类,实现银行的创建账户存钱取钱查询交易明细
  6. 关于linux的一些常用命令
  7. 仿京东的图片放大镜案例
  8. 表单识别(五)——票据识别-论文研读:基于深度学习的票据识别系统设计与实现,卞飞飞(上)
  9. 如何查看 github star 排行榜
  10. 服务器45G文件拷贝不下来,64GB的U盘既然不能拷贝一个8GB文件?我来告诉你答案及如何解决...