从使用 loader 到实现 loader · webpack

时间:2024-03-24 13:20:39

第 9 阶段:搞懂、搞透前端构建第 3 

网上看了很多讲 webpack 的 loader,受益颇深,今天从我个人的角度来讲讲什么是 loader。理解 loader 最关键的点是如何自己实现一个 loader,先不要理会 loader 的概念。

有人问了,我连 loader 是啥都不知道,我咋实现一个 loader,这里素燕告诉大家一个方法,看已有的 loader 是如何实现的,这里我以 less-loader 为例,它的作用是把 less 转换成 css。如果你不懂 less,可以看我们以前的课程 第19天:写出易复用、易维护、结构清晰的 CSS

使用 webpack 配置 loader 的时候,可以指定一个 options,它其实就是「大杂烩」,想放啥就放啥,为实现 loader 提供了参数配置入口,这样 loader 可以拿到配置中的参数来做一些事情。

从使用 loader 到实现 loader · webpack

我们看看 less-loader 支持的 options 都有哪些,一图胜前言:

从使用 loader 到实现 loader · webpack

既然 less-loader 支持了这些参数,那么它内部肯定会想方设法来实现这个功能。下载源代码:git clone https://github.com/webpack-contrib/less-loader.git。来到 package.json 文件,可以看到支持的命令:

从使用 loader 到实现 loader · webpack

我们今天的重点是彻底搞懂 loader,别走神!

webpack 打包的时候,会通过 webpack.config.js 中的配置 loader 来处理各种非 JS 文件,比如ts、less、scss。在实现 loader 的时候,webpack 提供了一个模块 https://github.com/webpack/loader-utils ,通过这个模块可以获得开发者配置的参数,同时这个模块还包含了一些工具方法。

1我先创建一个项目 day3-less,让这个项目支持 less,目录结果如下:

从使用 loader 到实现 loader · webpack

index.html HTML 页面模板:

从使用 loader 到实现 loader · webpack

index.js 入口文件,与 HTML 模板相关的 js 代码,这个需要注意一下,想让 webpack 能够打包 index.less 文件,必须要在 webpack 入口(entry)对这个样式文件进行引用,否则不会被打包:

从使用 loader 到实现 loader · webpack

index.less 样式文件

从使用 loader 到实现 loader · webpack

webpack.config.js 配置文件:

从使用 loader 到实现 loader · webpack

2、在 package.json 文件中配置 npm script,更详细内容可以查看 安装 webpack 搞定 Vue 打包

从使用 loader 到实现 loader · webpack

3、在 shell 中输入 npm run build 进行打包:

从使用 loader 到实现 loader · webpack

4、在浏览器中打开 index.html 文件,显示结果如下:

从使用 loader 到实现 loader · webpack

这说明我们成功地把 less 转换成了 css,不然样式肯定不对。那 less-loader 是如何实现的呢?

loader 本质是一个函数,我们创建一个 loader 文件夹和一个文件 suyanLessLoader.js,现在目录结构如下:

从使用 loader 到实现 loader · webpack

suyanLessLoader.js 文件中导出一个函数,看到没有 loader 本质是一个函数,参数 source 其实是 index.less 这个文件的内容。还记得我们刚才在 webpack 中配置 less-loader 的参数吗?可以通过 webpack 提供的 loader-utils 这个模块来获取。

从使用 loader 到实现 loader · webpack

前面我们提到的 loader 都是从 node_moudles 中导入的,那么如何使用自定义的 loader 呢?可以通过在 webpack.config.js 中配置查找 loader 的 path:

从使用 loader 到实现 loader · webpack

使用 suyanLessLoader 来处理 loader,需要在 less 文件的 rules 里修改 loader 配置:

从使用 loader 到实现 loader · webpack

执行一下 npm run build,

从使用 loader 到实现 loader · webpack

可以正常编译,但是当打开 index.html 文件时,发现样式并没有生效:

从使用 loader 到实现 loader · webpack

这是因为现在的 suyanLessLoader 并没有对 index.less 的内容进行处理。我们需要把 less 转换成 css。

less 官网提供了转换成 css 的方法,通过 npm i -D less 安装 less,安装完之后我们需要在 node 环境中使用 less,在 node_modules/less/dist/less.js 文件中有一个 render 函数,负责把 less 转换成 css,但这个方法是异步的,返回一个 promise 对象:

从使用 loader 到实现 loader · webpack

这点 webpack 已经考虑好了,自定义 loader 可以支持异步返回,最终 suyanLessLoader 的代码如下:

从使用 loader 到实现 loader · webpack

执行一下 npm run build,打开 index.html 文件,发现样式可以正常渲染了:

从使用 loader 到实现 loader · webpack

到此一个 mini 版的 less loader 就算完成了,但是官方的 less-loader 实现并没有这么简单,它支持了很多 options:

1、lessOptions:把 less 转换成 css 时,less.js 支持的参数;

2、prependData:在 less 源码之前添加额外的样式;

3、pendData:在 less 源码之后添加额外的样式;

4、sourceMap:记录解析后(css)与解析前(less)代码的位置,可以方便调试;

5、implemention:解析器,可以设置其它的 less 解析器;

这些 options 是为了服务千千万万开发者,毕竟不同的开发者需求不一样。

通过阅读 less-loader 源码,整体实现 loader 的步骤如下:

1、验证 options 的合法性

从使用 loader 到实现 loader · webpack

2实现自身提供的 options

从使用 loader 到实现 loader · webpack

3处理 source,index.less 文件中的内容;

从使用 loader 到实现 loader · webpack

到此一个完整的 loader 就实现了,但是想彻底搞懂 webpack 的工作原理还需要不断的去探索,比如 loader 是如何实现的,tabable 是什么。本节代码:https://github.com/lefex/FE/tree/master/webpack


本节完,诚挚邀请你来思考下面的问题并打卡:

1、平时工作中你用到了哪些 loader,它们的作用是啥?

2、总结一下自定义 loader 的步骤;

3、less 是如何转换成 css 的,本质原理是什么?

大家加油!


推荐阅读:

第 9 阶段:每位前端人都需要搞懂、搞透前端构建

https://webpack.js.org/contribute/writing-a-loader/

从使用 loader 到实现 loader · webpack