webpack 作为前端最火的构建工具, 是前端自动化工具链最重要的部分, 使用门槛较高. 本系列是笔者自己的学习记录, 比较基础, 希望通过问题 + 解决方式的模式, 以前端构建中遇到的具体需求为出发点, 学习 webpack 工具中相应的处理办法.(本篇中的参数配置及使用方式均基于 webpack4.0 版本)
一. loader 综述
loader 是 webpack 的核心概念之一, 它的基本工作流是将一个文件以字符串的形式读入, 对其进行语法分析及转换 (或者直接在 loader 中引入现成的编译工具, 例如 sass-loader 中就引入了 node-sass 将 SCSS 代码转换为 CSS 代码, 再交由 css-loader 处理), 然后交由下一环节进行处理, 所有载入的模块最终都会经过 moduleFactory 处理, 转成 javascript 可以识别和运行的代码, 从而完成模块的集成.
loader 支持链式调用, 所以开发上需要严格遵循 "单一职责" 原则, 即每个 loader 只负责自己需要负责的事情: 将输入信息进行处理, 并输出为下一个 loader 可识别的格式.
实际开发中, 很少会出现需要自己写 loader 来实现复杂需求的场景, 如果某个扩展名的文件无法快速集成到自动化构建工具里, 估计很快就会被抛弃了, 大家都那么忙是吧. 但是了解 loader 的基本原理和编译器的基本原理却是非常有必要的.
二. 如何写一个 loader
如果需要编写一个功能完整的 loader, 建议先到 webpack 的官方网站浏览一下 loader 有哪些 API, 地址: webpack 官网 - loader API https://www.webpackjs.com.api/loaders , 其中对于编写同步 loader, 异步 loader, 如何跳过 loader, 如何获取 options 配置项等等都做了非常详细的解释, 本篇中不再赘述.
假设现在要实现一个 dash-loader, 它的功能是加载并处理名称为 *.tpl.html 的文件, 将其变为一个 CommonJs 模块. 也就是说要完成一个如下的基本转换:
转换前的文本:
- <div>
- <h3 > 这里是标题 </h3>
- <p > 这里是内容 </p>
- </div>
转换后的文本:
- var str = '<div><h3 > 这里是标题 </h3><p > 这里是内容 </p></div>';
- module.exports = str;
那么 webpack.config.js 中需要增加如下的配置:
- ...
- module:{
- rules:[{
- test: /\.tpl\.html$/,
- use:[{
- loader:'dash-loader'
- }]
- }]
- }
在项目的 node_modules 依赖文件夹中新建 dash-loader 文件夹, 并在其中新建一个 index.js 文件, 内容的基本格式为:
- //index.js
- module.exports = function(source){
- var tpl="";
- source.split(/\r?\n/).forEach(function(line){
- line=line.trim();
- if(!line.length){
- return;
- }
- // 对 line 进行处理...
- tpl+=line;
- });
- return "var tpl=\'" + tpl + "\'\nmodule.exports = tpl";
- }
最终由 dash-loader 返回的数据就好像是从某个 CommonJs 模块中读入的一样了.
三. loader 的编译器本质
了解了 loader 的基本结构, 那么 loader 里到底应该写点什么才能完成代码转换呢? 这就涉及到了一个新的概念 -- 编译器 (Compiler). 一个基本的编译器, 需要经过 tokenize,parse,transform,stringify 几个核心步骤, 它的应用是非常广的, SPA 中的 virtual-DOM 的解析, babel 中的 ES6 语法解析等等, babel 的官网曾经推荐过一个非常棒的开源项目 (10k+Star), 详细讲述了如何一步一步实现一个编译器的, 建议感兴趣的同学可以自行学习:
[The-Super-Tiny-Compiler] --https://github.com/jamiebuilds/the-super-tiny-compiler https://github.com/jamiebuilds/the-super-tiny-compiler
[参考]
如何编写一个 loader
来源: https://www.cnblogs.com/dashnowords/p/9557372.html