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
示例
- 安装
2. 编辑配置文件
3. 执行编译命令
核心流程 —— 极度简化版
模块化 + 一致性
- 多个文件资源合并成一个,减少 http 请求数
- 支持模块化开发
- 支持高级 JS 特性
- 支持 Typescript、CoffeeScript 方言
- 统一图片、CSS、字体等其它资源的处理模型
- Etc...
使用 Webpack
关于 Webpack 的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:
- 流程类:作用于流程种某个 or 若干个环节,直接影响打包效果的配置项
- 工具类:主流程之外,提供更多工程化能力的配置项
流程类配置
配置总览
按使用频率:
entry/outputmodule/pluginsmodewatch/devServer/devtool
使用 Webpack
- 声明入口
entry
2. 声明产物出口
output3. 运行
npx webpack
处理 CSS
- 安装 Loader
2. 添加
module处理 css 文件
使用 webpack
问题:
- Loader 有什么作用?为什么这里需要用到 css-loader、style-loader
- 与旧时代 —— 在 HTML 文件中维护 css 相比,这种方式会有什么优劣势?
- 有没有接触过 Less、Sass、Stylus 这一类 CSS 预编译框架?如何在 Webpack 接入这些工具?
参考资料:
- Css-loader:github.com/webpack-con…
- Webpack 原理系列七:如何编写Loader:mp.weixin.qq.com/s/TPWcB4MfV…
- Style-loader:webpack.js.org/loaders/sty…
接入 Babel
- 安装依赖
2. 声明产物出口
output3. 执行
npx webpack
思考题:
- Babel 具体有什么功能?
- Babel 与 Webpack 分别解决了什么问题?为何两者能协作到一起了?
参考资料:
- Babel-loader:webpack.js.org/loaders/bab…
- Babel 官网:babeljs.io/
- @babel/preset-env:babeljs.io/docs/en/bab…
- @babel/preset-react:babeljs.io/docs/en/bab…
- @babel/preset-typescript:babeljs.io/docs/en/bab…
生成 HTML
- 安装依赖
2. 声明产物出口
output3. 执行
npx webpack
思考题:
- 相比于手工维护 HTML 内容,这种自动生成的方式有什么优缺点?
参考资料:
- html-webpack-plugin:webpack.js.org/plugins/htm…
工具线
HMR
- 开启 HMR
2. 启动 webpack
参考:《Webpack 原理系列十:HMR 原理全解析》mp.weixin.qq.com/s/cbYMpuc4h…
Tree-Shaking
Dead Code
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
- ...
Tree-Shaking
- 模块导出了,但未被其它模块使用
开启 tree-shaking:
mode:"production"optimization.usedExports:true
PS:对工具类库如 Lodash 有奇效
其它工具:
- 缓存
- Sourcemap
- 性能监控
- 日志
- 代码压缩
- 分包
- ...
思考题:
- 除上面提到的内容,还有哪些配置可划分为“流程类”配置?
- 工具类配置具体有什么作用?包括
devtool/cache/stat等 - Awesome-webpack-4plus github.com/Tecvan-fe/a…
- 《深入浅出 Webpack》 webpack.wuhaolin.cn/
- 《Survivejs - Webpack Book》 survivejs.com/webpack/pre…
进阶篇:理解 Loader
问题:Webpack 只认识 JS
为了处理分标准 JS 资源,设计出资源翻译模块 ———— Loader
用于将资源翻译为标准 JS
使用 Loader
- 安装 Loader
2. 添加
moudle处理 css 文件
认识 Loader:链式调用
- less-loader:实现 less => css 的转换
- css-loader:将 CSS 包装成类似 module.exports = "${css}" 的内容,包装后的内容符合 JavaScript 语法
- style-loader:将 css 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签
认识 Loader:其它特性
特点:
- 链式执行
- 支持异步执行
- 分 normal、pitch 两种模式
参考:Webpack 原理系列七:如何编写loader mp.weixin.qq.com/s/TPWcB4MfV…
如何编写 Loader
参考:Webpack 原理系列七:如何编写loader mp.weixin.qq.com/s/TPWcB4MfV…
常见 Loader
站在使用角度,建议掌握这些常见 Loader 的功能、配置方法
理解插件
思考题:
- Loader 输入是什么?要求的输出是什么?
- Loader 的链式调用是什么意思?如何串联多个 Loader?
- Loader 中如何处理异步场景?
进阶篇:理解插件
插件是什么?为什么这么设计?
很多知名工具,如:
- VS Code、Web Storm、Chrome、Firefox
- Babel、Webpack、Rollup、Eslint
- Vue、Redux、Quill、Axios
等等,都设计了所谓“插件”架构,为什么?
这是一个特别复杂的过程,那么:
- 新人需要了解整个流程细节,上手成本高
- 功能迭代成本高,牵一发动全身
- 功能僵化,作为开源项目而言缺乏成长性
- Blabla
心智成本高 => 可维护性低 => 生命力弱
插件架构精髓:对扩展开放,对修改封闭
甚至,Webpack 本身的很多功能也是基于插件实现的
使用 html-webpack-plugin使用 html-webpack-plugin + DefinePlugin
用起来很简单,但写起来很难
首先:插件围绕钩子展示钩子的核心信息:
- 时机:编译过程的特定节点,Webpack 会以钩子形式通知插件此刻正在发生什么事情;
- 上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信;
- 交互:在上下文参数对象中附带了很多存在 side effect 的交互接口,插件可以通过这些接口改变
时机:
compier.hooks.compilation
参数:compilation等
交互:dependencyFactories.set
思考题:
- Loader 与插件有什么区同点?
- “钩子”有什么作用?如何监听钩子函数?
参考:
- 《Webpack 插件架构深度讲解》mp.weixin.qq.com/s/tXkGx6Ckt…
- 《[万字总结]——文吃透 Webpack 核心原理》mp.weixin.qq.com/s/SbJNbSVzS…
学习方法
- 入门应用
- 理解打包流程
- 熟练掌握常用配置项、Loader、插件的使用方法,能够灵活搭建集成 Vue、React、Babel、Eslint、Less、Sass、图片处理等工具的 Webpack 环境
- 掌握常见脚手架工具的用法,例如:Vue-cli、create-react-app、@angular/cli
- 进阶
- 理解 Loader、Plugin机制,能够自行开发 Webpack 组件
- 理解常见性能优化手段,并能用于解决实际问题
- 理解前端工程化概念与生态现状
- 大师级
阅读源码,理解 Webpack 编译、打包原理,甚至能够参与共建