通俗易懂的教你编写自己的webpack loader与plugin

2023-11-11

前言

webpack几乎是目前前端开发者无人不知的打包框架,毕竟无论使用什么开发库,都会想到要使用webpack打包,包括各种脚手架cli工具,大部分也采用了webpack作为其打包工具。本文试图用最简单的代码(仅仅使用命令行工具,代码足够少)来编写自己的loader与plugin

初始化项目

// 运行npm init初始化package.json,一路回车
$ npm init
// 安装两个必须的依赖,前者为webpack核心,后者为命令行工具
$ npm install webpack webpack-cli
// 安装babel依赖
$ npm install @babel/core @babel/preset-env -D

简单来说,以上依赖已经足够去实现打包了,下面初始化一个待打包的工程文件。

// 项目根目录创建并编辑一个待打包的文件
$ vim main.js
// 加入以下待打包的代码
let foo = Math.random()
// 下边这个todo是模仿源代码中的todo,表示你还有未完成的功能。
// todo 
console.log(foo)

接着,编辑webpack的默认配置文件,保证可以打包源代码。

// 接着,编辑webpack的默认配置文件
$ vim webpack.config.js
// 添加一下的配置
module.exports = {
	entry: './main.js',
	module: {
		rules: [
			{
				test: /.js$/,
				use: ['babel-loader']
			}
		]
	}
}
// 打包,如果你没有全局安装webpack,是无法直接运行webpack的,因为没有加入环境变量。而npx可以自动去当前node_modules的bin目录中去寻找
$ npx webpack

如上,看到了吧,就是这样简单,接下来,我们以此为基础,添加loader和plugin。
需求如下

  • 如果代码中出现 // todo 则替换为一个警告。这样代码执行的之后,可以发现问题。
  • 将最终打包出的代码,移动到cdn目录,来模拟静态资源上传CDN的过程。

正戏开始

首先介绍一下loader与plugin的区别。loader用于编译代码,大部分情况下是把原来无法直接在浏览器运行的代码编译为可执行的代码,比如对ES6,Sass的编译。而plugin则是在特定的时间点对编译的资源进行操作,比如压缩代码,或将打包出的文件打入到Html中。具体看看下边的实战,想必你会有更深的理解。

todo-loader

对于第一个需求,首先编写loader。一个loader就是一个npm包,所以操作如下:

// 创建loader的文件夹
$ mkdir todo-loader
// 初始化一个npm包,之后一路回车
$ npm init
// 创建并编辑入口文件
$ vim index.js
// 这就是核心
module.exports = function(resource){
  console.log('加载todo-loader啦')
  const result = resource.replace(/\/\/\stodo/, 'console.warn("请完成todo")')
  return result;
}

简单来说,一个loader的实现就是去实现一个函数,传入文件源代码resource然后进行你想要的修改。之后再把它返回出来,以便下一个loader继续处理。可以看一下输出的结果:

// 源代码
let foo = Math.random()
// todo
console.log(foo)

// 打包输出
(()=>{var o=Math.random();console.warn("请完成todo"),console.log(o)})();

以上可以看出已经完成了对todo注释的替换。支持已经实现了一个loader ^ ^

cdn-plugin

下面来实现上传CDN的plugin,事实上loader和plugin其实就是按照webpack的规矩办事即可。在webpack的构建过程中,会在特定的时机广播事件。这就好像是Vue/React的生命周期钩子函数。plugin只需要在对应的钩子(事件回调)函数中完成想要的操作,比如在最终打包完成的钩子函数中上传文件到CDN,简单来说过程如下:

  • 初始化一个plugin的npm包
  • 编辑index.js文件,创建一个构造函数,函数内部实现一个apply方法(按规矩办事)
  • 监听打包成功的事件,并完成上传CDN的操作。
const child_process = require('child_process')
class UploadCDNPlugin {
  constructor(options){
    // 根据用户参数去定制
  }
  // 核心方法
  apply(compiler) {
    // 监听回调方法
    compiler.hooks.afterEmit.tap(
        'UploadCDNPlugin',
        (compilation) => {
        	// 原路径
        	const src = compilation.compiler.outputPath;
        	// 目标路径
        	const cdn = src.replace(/\/\w+$/,'/cdn');
        	// 模拟上传,实际可能是调用网络IO接口而不是磁盘IO的接口
        	child_process.exec(`cp -r ${src} ${cdn}`, err=>{console.log(err)} );
        }
    );
  }
}
module.exports = UploadCDNPlugin;

接着只要在webpack中引入该插件即可

// 这里引入有三种方式
1. npm link 本文使用这种方式
2. 直接require一个js文件
3. 发布到私服或者npm
const  UploadCDNPlugin = require('cdn-plugin');
...
plugins: [
   new UploadCDNPlugin()
]

结束语

weback有两个核心部分需要了解到

  • 构建机制
  • 生成的bundle.js在浏览器的运行机制

本文描述了其构建机制,从上述loader编译到plugin的钩子函数,不难看出,webpack的构建流程就像流水线一样,各个loader与plugin各司其职。将你的代码"交给各个工人去操作",最终完成完整的打包流程,简单而优雅。

参考

  1. webpack官方文档 https://webpack.js.org/api/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通俗易懂的教你编写自己的webpack loader与plugin 的相关文章

随机推荐

  • OpenCV部署CRNN文字识别

    一 参考链接 1 模型获取及训练 2 github解答 二 模型转化 pytorch 转 ONNX import torch import models crnn as crnn model crnn CRNN 32 1 37 256 mo
  • dotfuscator使用方法

    转载自 http hi baidu com free3people item 0fba87d34091df15d80e4400 dotfuscator如何对 net程序进行混淆保护对于程序代码的保护 网上有很多资料 有的说混淆 有的说加密
  • jsp中使用response.sendRedirect重定向页面传递中文参数

    1 要跳转的jsp页面的书写 2 跳转的jsp页面对参数的获取 使用jsp内置对象
  • Linux read的核心函数generic_file_buffered_read

    内核 5 9 0 流程图 generic file buffered read一种调用路径 cat某个文件触发 0 ondemand readahead mapping 0xffff888005c61340 ra 0xffff8880059
  • 启动Fiddler导致浏览器显示“您的连接不是私密连接”

    浏览器出现如下问题 解决 在浏览器受信任的根证书颁发机构列表中添加fiddler证书 fiddler导出根证书 谷歌浏览器证书管理 受信任的根证书颁发机构列表中添加fiddler证书 注意 如果以上操作后还是无效 就在fiddler先重置根
  • Tracy JS 小笔记 - 运算符,条件语句,循环

    运算符 数学运算和字符串连接 任何数据加上字符串都等于字符串 var a 1 1 a 1 2 a 2a12 var a 1 1 a 1 2 a 2a3 var a aa true a aatrue var a 1 0 a NaN NaN N
  • 基于CentOS系统的网站搭建(入门级)

    准备 使用到的网站 非广告 阿里云 https www aliyun com utm content se 1008364713 宝塔面板 宝塔面板下载 免费全能的服务器运维软件 以阿里云为例 入门选择 轻量级应用服务器 选择服务器配置 选
  • 7-3 两个有序链表序列的合并 (20 分)

    已知两个非降序链表序列S1与S2 设计函数构造出S1与S2合并后的新的非降序链表S3 输入格式 输入分两行 分别在每行给出由若干个正整数构成的非降序序列 用 1表示序列的结尾 1不属于这个序列 数字用空格间隔 输出格式 在一行中输出合并后新
  • Redis之十大类型(三)(下)

    3 6 Redis位图 bitmap 由 0 和 1 表示的二进制位的 bit 数组 介绍 用String类型作为底层数据结构实现的一种统计二值状态的数据类型 位图本质是数组 它是基于String数据类型的按位的操作 该数组由多个二进制位组
  • 机器学习之K-means原理详解、公式推导、简单实例(python实现,sklearn调包)

    目录 1 聚类原理 1 1 无监督与聚类 1 2 K均值算法 2 公式推导 2 1 距离 2 2 最小平方误差 3 实例 3 1 python实现 3 2 sklearn实现 4 运行 可直接食用 1 聚类原理 1 1 无监督与聚类 在这部
  • 图像处理中常用数学知识

    2 3 3 赋范空间 每个实数或复数 都有相对应的绝对值或者模 每一个n维矢量 也都可以定义其长度 如果把 长度 的概念推广到一般抽象空间中的元素上 就可以得到范数这个概念 本节完 2 3 6 希尔伯特空间 定义 在由内积所定义的范数意义下
  • windows的cmd常用命令

    文章目录 一 位 二 cmd基本操作 1 win R启动运行 2 打开cmd 3 运行的命令 三 cmd常用命令 1 功能性命令 2 文件操作 3 shutdown 4 tasklist命令 5 taskkill命令 6 查看日志 四 cm
  • vue项目启动Error: Cannot find module ‘imagemin-gifsicle‘

    Error Cannot find module imagemin gifsicle 依赖没有安装完全 可以删除module 然后重新安装依赖
  • C语言学习:平方-->乘方(m的n方)

    平方 直接用两个数 或变量 相乘就可以表示平方 比如x x 不过如果 需要求m的n次方 就需要用到pow x y 乘方 包括开方 这个库函数了 使用pow x y 这个库函数 需要math h头文件 其中x和y都是双精度浮点 double
  • [FPGA开发]解决正点原子Xilinx下载器无法下载、灯不亮的问题

    问题描述 使用正点原子的Xilinx下载器下载时 电脑无法识别下载器 Vivado无法识别开发版 问题解决 1 检查XIlinx下载器的灯是否亮起 亮灯 说明 解决方法 红灯亮起 下载器可以连接到PC 检查开发版是否供电正常 蓝灯亮起 下载
  • pytorch测试模型时根据不同列别的概率值得到具体的分类

    pytorch 分类任务的教程 https pytorch org tutorials beginner blitz cifar10 tutorial html 主要使用的是 predict torch max out data 1 最后的
  • best ajax lib,BEST Currency Converter

    想提升客户的购物体验 以当地货币显示价格可以省去他们很多不必要的时间 也能提升客户与平台的粘度 该插件具备如下优势 1 轻松添加多种货币 按下按钮即可添加160多种货币 像专业人士一样开始国际销售 并鼓励客户购买 2 自动转换价格 价格会根
  • node.js 读取文件的时候 cmd执行脚本,中文(汉字)打印不出来

    node js 读取文件的时候 cmd执行脚本 中文 汉字 打印不出来 文本详情 输出结果 问题原因 txt编码格式不是UTF 8 解决办法 打开TXT文件 点击 文件 gt 另存为 gt 编码改为UTF 8 保存替换 问题解决
  • 【大数据】Flink 详解(五):核心篇 Ⅳ

    本系列包含 大数据 Flink 详解 一 基础篇 大数据 Flink 详解 二 核心篇 大数据 Flink 详解 三 核心篇 大数据 Flink 详解 四 核心篇 大数据 Flink 详解 五 核心篇 大数据 Flink 详解 六 源码篇
  • 通俗易懂的教你编写自己的webpack loader与plugin

    前言 webpack几乎是目前前端开发者无人不知的打包框架 毕竟无论使用什么开发库 都会想到要使用webpack打包 包括各种脚手架cli工具 大部分也采用了webpack作为其打包工具 本文试图用最简单的代码 仅仅使用命令行工具 代码足够