这是我参与「第四届青训营 」笔记创作活动的的第17天。
Webpack 知识体系
一、为什么要学习 Webpack
⭐ 理解前端"工程化"概念、工具、目标
⭐ 一个团队总要有那么几个人熟悉 Webpack,某种程度上可以成为个人的核心竞争力
⭐ 高阶前端必经之路
二、什么是 Webpack
前端项目由什么构成?—— 资源
手动管理资源
⭐ 依赖手工,比如有50个 JS 文件操作,过程繁琐
⭐ 当代码文件之间有依赖的时候,就得严格按依赖顺序书写
⭐ 开发与生产环境一致,难以接入 TS 或 JS 新特性
⭐ 比较难接入 Less、Sass 等工具
⭐ JS、图片、cSS资源管理模型不一致
工程化工具
❓ 本质上是一种前端资源编译、打包工具
⭐ 多份资源文件打包成一个 Bundle
⭐ 支持 Babel、Eslint、TS、CoffeScript、Less、Sass
⭐ 支持模块化处理 css、图片等资源文件
⭐ 支持 HMR + 开发服务器
⭐ 支持持续监听、持续构建
⭐ 支持代码分离
⭐ 支持 Tree-shaking
⭐ 支持 Sourcemap
三、使用 Webpack
示例
-
安装:
npm i -D webpack webpack-cli -
编辑配置文件
module.exports = {
entry: 'main.js',
output: {
filename: "[name].js"
path: path.join(__dirname, "./dist"),
},
module: {
rules: [{
test: /\.less$/i,
use:['style-loader', 'css-loader', 'less-loader']
}]
}
}
- 执行编译命令:
npx webpack
核心流程
模块化 + 一致性
- 多个文件资源合并成一个,减少http请求数
- 支持模块化开发
- 支持高级 JS 特性
- 支持 Typescript、CoffeeScript 方言
- 统一图片、CSS、字体等其它资源的处理模型
配置总览
⭐ 按使用频率:
entry/outputmodule/pluginsmodewatch/devServer/devtool
流程类配置
使用
处理 CSS
⭐ 参考资料:
接入 Babel
⭐ 参考资料:
生成 HTML
⭐ 参考资料: Html-Webpack-Plugin
工具类配置
HMR
- 开启 HMR
module.exports = {
// ...
devServer: {
hot: true
}
};
- 启动 Webpack:
npx webpack serve
⭐ 参考资料: Webpack 原理系列十:HMR 原理全解析
Tree - Shaking
⭐ Tree-shaking —— 树摇,用于删除 Dead Code
⭐ Dead Code:
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
⭐ Tree-Shaking:模块导出了,但未被其它模块使用
开启 tree - shaking:mode: "production" optimization.usedExports: true
其他工具
- 缓存
- Sourcemap
- 性能监控
- 日志
- 代码压缩
- 分包
四、理解 Loader
❓ Webpack 只认识 JS:为了处理非标准 JS 资源,设计出资源翻译模块—— Loader,用于将资源翻译为标准 JS
使用 Loader
- 安装 Loader:
npm add -D css-loader style-loader less-loader - 添加
module处理css文件
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
"less-loader",
],
},
],
},
};
链式调用
⭐ less - loader:实现 less => css 的转换
⭐ css - loader:将 CSS 包装成类似 module.exports = "${css}" 的内容,包装后的内容符合 JavaScript 语法
⭐ style - loader:将 css 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签
其他特性
- 链式执行
- 支持异步执行
- 分 normal、pitch 两种模式
如何编写 Loader
module.exports = function(source, sourceMap?, data?) {
// source为 loader 的输入
// 可能是文件内容,也可能是上一个 loader 处理结果
return source;
};
常见 Loader
五、理解插件
为什么设计"插件"架构
⭐ 提升整个应用或工具的扩展性
⭐ 需要修改工具功能,这是一个特别复杂的过程,那么∶
- 新人需要了解整个流程细节,上手成本高
- 功能迭代成本高,牵一发动全身
- 功能僵化,作为开源项目而言缺乏成长性
- 心智成本高=>可维护性低=>生命力弱
⭐ 插件架构精髓:对扩展开放,对修改封闭
钩子
钩子的核心信息
- 时机:编译过程的特定节点,Webpack 会以钩子形式通知插件此刻正在发生什么事情;
- 上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信息;
- 交互:在上下文参数对象中附带了很多存在 side effect 的交互接口,插件可以通过这些接口改变。
举例
- 时机:
compier.hooks.compilation - 参数:
compilation等 - 交互:
dependencyFactories.set
参考资料
六、学习方法
学习阶段
- 入门应用
- 理解打包流程
- 熟练掌握常用配置项、Loader、插件的使用方法,能够灵活搭建集成Vue、React、Babe1、Eslint、Less、Sass、图片处理等工具的Webpack环境
- 掌握常见脚手架工具的用法,例如:Vue-cli、create- react-app、@angular/cli
- 进阶
- 理解 Loader、Plugin 机制,能够自行开发 Webpack 组件
- 理解常见性能优化手段,并能用于解决实际问题
- 理解前端工程化概念与生态现状
- 大师级
- 阅读源码,理解 Webpack 编译、打包原理,甚至能够参与共建