这是我参与「第四届青训营 」笔记创作活动的的第12天
为什么要学习 Webpack ?
- 理解前端“工程化”概念、工具、目标
- 一个团队总要有那么几个人熟悉 Webpack (大部分的工程环境都基于 Webpack),某种程度上可以成为个人的核心竞争力
- 高阶前端必经之路
课程目标
- 理解 Webpack 的基本用法
- 通过介绍 Webpack 功能、 Loader 与 Plugin 组件设计,建立一个知识体系
- 不会事无巨细的介绍 Webpack 所有
- 也不是深入源码,讲解底层实现原理
什么是 Webpack
前端项目由什么构成? —— 资源(PNG 、 JPG 、 GIF 、 WEBP 、 JS 、 TS 、 CSS 、 Less 、 ……)
09年之前都是页面直接管理(手动管理)资源文件,比如用 link 标签引入 style 文件。
手动管理对开发速率的影响:
- 依赖手工,比如有50个 JS 文件……操作,过程繁琐
- 当代码文件之间有依赖的时候就得严格按照依赖顺序书写
- 开发与生产环境一致,难以接入 TS 或 JS 新特性
- 比较难接入 Less 、 Sass 等工具
- JS 、图片、 CSS 资源管理模型不一致
Webpack 本质上是一种前端资源编译、打包工具。
编译是为了应对图片、 Less 、 Sass 、 TS 等非标准的 JS 文件,把它编译成标准的 JS 内容。
把编译好的内容再打包成一个 Bundle ,为什么要打包呢?因为 Webpack 刚出来时浏览器不支持 ESM 模式,所以当时要把资源放在浏览器里面运行必须一个一个去引入资源, Webpack 要做就是把所有资源打包成一个文件,那我就只需要插入一个 script 。
- 多份资源文件打包成一个 Bundle 。
- 支持 Babel 、 Eslint 、 TS 、 CoffeScript 、 Less 、 Sass 等其它工程化工具,这些工具都可以变成 Webpack 的一个组件,变成 Webpack 工作流里面的一个步骤去运行。
- 支持模块化处理 CSS 、图片等资源文件,统一了这些资源的管理模型,我们不需要再为 CSS 、图片等非 JS 的资源独立的去设计一套管理的规范。
- 支持 HMR + 开发服务器。
- 支持持续监听、持续构建。
- 支持代码分离。
- 支持 Tree-shaking 。
- 支持 Sourcemap 。
- ……
使用 Webpack
-
示例
- 安装:
npm i -D webpack webpack-cli - 编辑配置文件
- 执行编译命令:
npx webpack
打包后的部分 main.js 代码:
- 安装:
-
核心流程 —— 极度简化版
-
模块化 + 一致性
Webpack 本质上就做了两件事情:模块化 + 一致性。
模块化:支持对不同类型的资源都用 import 、 require 这些语句去管理这些资源。- 多个文件资源合并成一个,减少 http 请求数
- 支持模块化开发
- 支持高级 JS 特性
- 支持 TypeScript 、 CoffeeScript 方言
- 统一图片、 CSS 、字体等其它资源的处理模型
- Etc……
-
使用 Webpack 关于 Webpack 的使用方法,基本都围绕“配置”展开,而这些配置大致都可划分为两类:
-
流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项(以下是部分配置项)
-
工具类:主流程之外,提供更多工程化能力的配置项。
配置总览:Webpack 配置官方文档
-
-
使用 Webpack
文件结构:
- 声明入口 entry
- 声明产物出口 output
- 运行
npm webpack
- 声明入口 entry
-
处理 CSS
文件结构:
- 安装 Loader :
npm add -D css-loader style-loader - 添加 module 处理 css 文件
- 安装 Loader :
-
接入 Babel
文件结构:
- 安装依赖:
npm i -D @babel/core @babel/preset-env babel-loader - 声明产物出口 output
- 执行:
npx weboack
- 安装依赖:
-
生产 HTML 文件结构:
- 安装依赖:
npm i -D html-webpack-plugin - 声明产物出口 output
- 执行:
npx weboack
- 安装依赖:
-
工具线具体的用法 —— HMR (Hot Module Replacement ,模块热替换,写的代码能够立刻被更新到浏览器上并且浏览器是不需要刷新的)
Webpack 原理系列十:HMR 原理全解析
- 开启 HMR
- 启动 Webpack :
npx webpack serve
- 开启 HMR
-
工具线具体的用法 —— Tree-Shaking
Tree-Shaking 是树摇,本质上是用于删除一些 Dead Code (没有用到的代码)。
Dead Code :- 代码没有被用到,不可到达
- 代码的执行结构不会被用到
- 代码只读不写
- ……
Tree-Shaking :模块导出了,但未被其它模块使用。
开启 Tree-Shaking :
- "mode": "production"
- "optimization.usedExports": true
-
其它工具
- 缓存
- sourcemap
- 性能监控
- 日志
- 压缩代码
- 分包
- ……
进阶篇:理解 Loader
loader 核心功能:把非 JS 的资源转换成 JS 的资源。
-
使用 Loader
- 安装 Loader :
npm add -D css-loader style-loader less-loader - 添加 module 处理 css 文件
- 安装 Loader :
-
认识 Loader :链式调用
- less-loader :实现 less => css 的转换。
- css-loader :将 CSS 包装成类似 module.exports = "${css}" 的内容,包装后的内容符合 JavaScript 语法。
- style-loader :将 css 模块包进 require 语句并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签。
Loader 它在运行时会一个一个的逐步的去执行每一个 loader ,这是 Webpack 的运行机制。
-
认识 Loader :其它特性
在运行一开始的时候会有一个 pitch 阶段,在 pitch 阶段会有一个特性就是任意一个 loader 的 pitch 阶段有返回值的话它就会停止后面的执行,这特性特别适合用来做一些 catch 。
执行阶段结束会变成标准的 JavaScript 代码。
特点:- 链式执行
- 支持异步执行
- 分 normal 、 pitch 两种模式
-
常见 Loader 站在使用角度,建议掌握这些常见 Loader 的功能、配置方法
进阶篇:理解 Plugin
很多知名工具(VS Code 、 Chrome 、 Babel 、 Vue)都设计了所谓“插件”架构,为什么?
因为可以能提升整个应用的扩展性或者说工具的扩展性。
Webpack 的源码、主流层次非常非常的复杂,那么:
- 新人需要了解整个流程细节,上手成本高
- 功能迭代成本高,牵一发动全身
- 功能僵化,作为开源项目而言缺乏成长性
- Blabla
心智成本高 => 可维护性低 => 生命力弱
插件架构精髓就是对扩展开放,对修改关闭的思维(只做最核心的那一部分,但是开放一系列的扩展方式、修改方式)。
- 首先:插件围绕“钩子”展开
钩子某种程度上可以理解为一个事件,但是这个事件会比普通的事件复杂一点。
钩子的核心信息(复杂一点):
- 时机:编译过程的特定节点, Webpack 会以钩子形式通知插件此刻正在发生什么事情;
- 上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信息;
- 交互:在上下文参数对象中附带了许多存在 side effect 的交互接口,插件可以通过这些接口改变。
简化、关键的钩子:
时机:"compier.hooks.compilation"
参数:"compilation"等
交互:"dependencyFactories.set"
如何学习 Webpack
- 入门级:学会灵活使用
- 理解打包流程
- 熟练掌握常用配置项、 Loader 、 插件的使用方法,能够灵活搭建集成 Vue 、React 、 Babel 、 Eslint 、 Less 、 Sass 、 图片等工具的 Webpack 环境
- 掌握常见脚手架工具的用法,例如: Vue-cli 、 create-react-app 、 @angular/cli
- 进阶:学会扩展 Webpack
- 理解 Loader 、 Plugin 机制、能够自行开发 Webpack 组件
- 理解常见性能优化手段并能用于解决实际问题
- 理解前端工程化概念与生态现状
- 大师:源码级理解 Webpack 打包编译原理
- 阅读源码、理解 Webpack 编译、打包原理,甚至能够参与共建