什么是 Webpack、Webpack 打包核心流程、使用 Webpack、理解 Loader、理解插件、学习方法
# Webpack 知识体系
# 为什么要学习 Webpack
- 理解前端 “工程化” 概念、工具、目标
- 一个团队总要有那么几个人熟悉 Webpack,某种程度上可以成为个人的核心竞争力
- 高阶前端必经之路
# 什么是 Webpack
前端项目由许多不同类型的文件、资源构成,比如:
我们当然可以手动管理这些资源,而且在旧时代我们也的确是这样做的,比如:
但是,会有许多潜在问题:
-
依赖手工,比如有 50 个 JS 文件… 操作,过程繁
琐 -
当代码文件之间有依赖的时候,就得严格按依
赖顺序书写 -
开发与生产环境一致,难以接入 TS 或 JS 新特
性 -
比较难接入 Less、Sass 等工具
-
JS、图片、CSS 资源管理模型不一致
这些都是旧时代非常突出的问题,对开发效率影响非常大,直到… 出现了很多的工程化工具,比如:webpack、vite、esbuild、rollup.js 等等
某种程度上,正是这些工具的出现,才有了 “前端工程” 这一概念
webpack 本质上是一种前端资源编译、打包工具:
- 多份资源文件打包成一个 Bundle
- 支持 Babel、Eslint、TS、CoffeScript、Less、Sass
- 支持模块化处理 css、图片 等资源文件
- 支持 HMR + 开发服务器
- 支持持续监听、持续构建
- 支持代码分离
- 支持 Tree-shaking
- 支持 SourceMap
简单示例:
-
安装:
npm install webpack
-
编辑配置文件:
webpack.config.js
const path = require('path');
module.exports = {
}
-
执行编译命令:
npx webpack
# Webpack 打包核心流程
核心流程:
# 使用 Webpack
使用 Webpack 的好处:
- 多个文件资源合并成一个,减少 http 请求数支持模块化开发
- 支持高级 JS 特性
- 支持 Typescript、CoffeeScript 方言
- 统一图片、CSS、字体等其它资源的处理模型
关于 Webpack 的使用方法,基本都围绕 “配置” 展开,而这些配置大致可划分为两类:
-
流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项
-
工具类:主流程之外,提供更多工程化能力的配置项
# 解析 CSS
Loader 有什么作用?为什么这里需要用到 css-loader、style-loader?
与旧时代 —— 在 HTML 文件中维护 css 相比,这种方式会有什么优劣处?
有没有接触过 Less、Sass、Stylus 这一类 CSS 预编译框架?如何在 Webpack 接入这些工具?
# 解析 JS
Babel:一个 JS 的降级化转义器,为了让 ES6 等新语言特性能够兼容尽量多的浏览器,需要将 ES6 等新语言特性装换成 ES5 等兼容性更强的代码
接入 Babel:
-
安装依赖:
npm i -D @babel/core @bebel/preset-env babel-loader
-
声明产物出口
output
: -
执行
npx webpack
Babel 具体有什么功能?
Babel 与 Webpack 分别解决了什么问题?为何两者能协作到一起了?
# 生成 HTML
当各种资源文件都已经由 Webpack 统一管理后,HTML 也不必要我们自己维护,可以使用 Webpack 插件生成
接入 html-webpack-plugin
:
相比于手工维护 HTML,使用 Webpack 自动化有什么优缺点?
# 模块热替换 - HMR
-
开启 HMR
module.exports = {
// 其他配置项...
devServer: {
hot:true
},
watch: true // 持续监听本地文件变化并即时构建
}
-
…
# Tree-Shaking
删除未被使用的代码(Dead Code):
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
使用:
- 只需要配置
mode = "production"
和optimization.usedExports = true
即可
PS:对工具类库,如 Lodash 有奇效
# 其他工具
缓存、SourceMap、性能监控、日志、代码压缩、分包等等
-
除上面提到的内容,还有哪些配置可划分为 “流程类” 配置?
-
工具类配置具体有什么作用?包括
devtool/cache/stat
等
# 理解 Loader
为什么需要 Loader:因为 Webpack 只认识 JS,所以为了处理非标准 JS 资源,设计出资源翻译模块 ——Loader,用于将资源翻译为标准 JS
Loader 特性:链式调用、支持异步执行、分 normal/pitch 两种模式
# 链式调用
以 Less 语法文件的解析为例:
-
less-loader:实现 less => css 的转换
-
css-loader:将 CSS 包装成类似 module.exports = “${css}” 的内容,包装后的内容符合 JavaScript 语法
-
style-loader:将 css 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签
# 如何编写 Loader
Loader 输入是什么?要求的输出是什么?
Loader 的链式调用是什么意思?如何串联多个 Loader ?
Loader 中如何处理异步场景?
# 理解插件
很多知名工具,如:
- VS Code、Web Storm、Chrome、Firefox
- Babel、Webpack、Rollup、Eslint
- Vue、Redux、Quill、Axios
等等,都设计了所谓 “插件” 架构,为什么?
工具的源码和工作原理是一个特别复杂的过程,那么∶
-
新人需要了解整个流程细节,上手成本高
-
功能迭代成本高,牵一发动全身
-
功能僵化,作为开源项目而言缺乏成长性
-
学习的心智成本高 => 可维护性低 => 生命力弱
插件架构精髓:对扩展开放,对修改封闭
# 钩子
钩子的核心信息∶
-
时机:编译过程的特定节点,Webpack 会以钩子形式通知插件此刻正在发生什么事情
-
上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信息义
-
交互:在上下文参数对象中附带了很多存在 side effect 的交互接口,插件可以通过这些接口改变
# 学习方法
-
入门应用
- 理解打包流程
- 熟练掌握常用配置项、Loader、插件的使用方法,能够灵活搭建集成 Vue、React、Babel、Eslint、Less、Sass、图片处理等工具的 Webpack 环境
- 掌握常见脚手架工具的用法,例如:Vue-cli、create-react-app、@angular/cli
-
进阶
-
理解 Loader、Plugin 机制,能够自行开发 Webpack 组件
-
理解常见性能优化手段,并能用于解决实际问题
-
理解前端工程化概念与生态现状
-
-
大师级
- 阅读源码,理解 Webpack 编译、打包原理,甚至能够参与共建
Webpack 进阶知识体系
# 参考资料
- 字节青训营课程