这是我参与「第五届青训营 」笔记创作活动的第20天。
一、本堂课的重点内容
- Webpack Loader
- Webpack 插件
二、详细知识点介绍
问题:Webpack只认识JS
Loader
处理非标准js资源,实现内容转化,用于将资源翻译为标准js
以处理less为例:
- 安装loader,
npm add -D css-loader style-loader less-loader - 添加module处理css文件
module: {
rules: [{
test: /.less$/i,
use: [
"style-loader",
"css-loader",
"less-loader"
]
}]
}
Loader的链式调用
前面loader的输出作为后面loader的输入,各个loader内部的功能比较内聚。
处理less的Loader的运行流程:
- less-loader:实现less到css的转换
- css-loader:将CSS包装成类似
module.exports="${css}"的内容,包装后的内容符合JavaScript语法 - style-loader:将css模块包进require语句,并在运行时调用injectStyle等函数将内容注入到也没的style标签。
在Webpack的Loader Runner内,进入Webpack的make函数,先调用less-loader,将less的内容转化成一段css代码,进入css-loader中,css-loader输出一个字符串,再进入style-loader中,生成一段包含injectStyleIntoStyleTag的函数,在浏览器运行时会执行该函数,将css代码插入到HTML页面中。
pitch阶段根据Webpack的config的module中use数组定义的顺序,依次向后执行,任意loader的pitch阶段有返回值就会停止后面的执行,可用于做catch。
执行阶段从数组的最后一项开始执行,通过链式调用不断向前调用,直到执行结束变成标准的js代码,回到Webpack中。
执行特点:
- 链式执行
- 支持异步执行
- 分normal、pitch两种模式
ndb npx webpack可通过ndb进行调试。
编写loader
loader格式:
module.exports = function (source, sourceMap, data) {
//source为源码内容
//sourceMap可选,若前面的loader生成了sourceMap,则会传入
//data可选,其他的信息
return source;
};
常用Loader:
插件
插件能提高整个工具或应用的扩展性
插件架构的精髓:对扩展开放,对修改封闭;应用只做最核心的部分,但是开放一系列的扩展和修改方式,可以通过扩展和修改方式扩充细节。
Webpack是一堆插件组合的结果
插件的使用
- 安装插件,
npm add -D xxx - 导入插件,
const xxx=require('xxx') - 在webpack.config.js中new一个插件的实例,
plugins:[new 插件名()],有的插件需要传入参数
理解插件
钩子:
- 时机,编译过程的特定节点,Webpack会以钩子形式通知插件此刻正在发生的事,
compier.hooks.compilation - 上下文,通过tapable提供的回调机制,以参数方式传递上下文信息,
compilation - 交互,在上下文参数对象中附带了很多存在side effect的交互接口,插件可以通过这些接口改变,
dependencyFactories.set
Webpack学习方法
入门应用
- 理解Webpack打包流程
- 熟练掌握常用配置项、Loader、插件使用方法,能够灵活搭建集成Vue、React、Babel、Eslint、Less、Sass、图片处理等工具的Webpack环境
- 掌握常见脚手架工具的用法,如Vue-cli、create-react-app、@angular/cli,提升效率
- 能用起来,知道怎么用,知道是干嘛的
进阶
- 理解Loader、Plugin机制,能够自行开发Webpack组件,通过自己写提高理解深度
- 理解常见性能优化手段,并能用于解决实际问题,如cache等
- 理解前端工程化概念与生态现状,与Vite等框架的比较
大师级
阅读源码,理解Webpack编译、打包原理,甚至能够参与共建
三、实践练习例子
ESlint Loader示例: eslint-loader/index.js at master · webpack-contrib/eslint-loader (github.com)
import getOptions from './getOptions';
import Linter from './Linter';
import cacheLoader from './cacheLoader';
export default function loader(content, map) {
const options = getOptions(this);
const linter = new Linter(this, options);
this.cacheable();
// return early if cached
if (options.cache) {
cacheLoader(linter, content, map);
return;
}
linter.printOutput(linter.lint(content));
this.callback(null, content, map);
}
四、课后个人总结
本节课学习了Webpack的Loader和插件的用法和原理,Webpack通过Loader,处理非js文件,将非js文件转为js。而插件使Webpack更具扩展性,通过学习理解了插件的精髓,对扩展开放,对修改封闭。本节课还学习了Webpack的学习路线,了解了不同阶段应达到的目标。Webpack作为前端工程化重要的编译、打包和压缩工具,需要进一步学习研究。
五、参考链接
Webpack 原理系列七:如何编写loader (qq.com)
Webpack 知识体系.pptx - 飞书云文档 (feishu.cn)