Webpack 知识体系 | 青训营笔记

56 阅读4分钟

这是我参与「第四届青训营」笔记创作活动的的第18天

什么是 Webpack

Webpack 5 知识体系

发展历程

前端项目由资源构成: PNG、JPG、GIF、WEBP、JS、TS、CSS、Less、Vue、JSX、Sass...

手动管理这些资源:

缺点:

  • 依赖手工,比如有 50 个 JS 文件,操作,过程繁琐
  • 当代码文件之间有依赖的时候,就得严格按依赖顺序书写
  • 开发与生产环境一致。难以接入 TS 或 JS 新特性
  • 比较难接入 Less、Sass 等工具
  • JS、图片、CSS 资源管理模型不一致

这些都是旧时代非常突出的问题,对开发效率影响非常大,直到:

出现了很多工程化工具:

某种程度上正足这些工具的出现,才有“前端工程”这一概念

什么是 Webpack

Webpack 本质上是一种前端资源编译、打包工具

  • 多份资源文件打包成一个 Bundle
  • 支持 Babel、Eslint、TS、CoffeScript、 Less、Sass
  • 支持模块化处理 CSS、图片等资源文件
  • 支持 HMR + 开发服务器
  • 支持持续监听、持续构建
  • 支持代码分离
  • 支持 Tree-shaking
  • 支持 Sourcemap

使用 Webpack

安装配置

1. 安装

npm i -D webpack webpack-cli

2. 编辑配置文件

entry: 当前项目的入口
output: 当前项目打包完成后的文件名和位置

3. 执行编译命令

npx webpack

结果

核心流程

  1. 入口处理

从 "entry" 文件开始,启动编译流程

  1. 依赖解析

从 "entry" 文件开始,根据 "require" or "import" 等语句找到依赖资源

  1. 资源解析

根据 "module" 配置,调用资源转移器,将 png、css 等非标准 JS 资源转译为 JS 内容;

递归调用2、3,直到所有资源处理完毕

  1. 资源合并打包

将转译后的资源内容合并打包为可直接在浏览器运行的 JS 文件

模块化 + 一致性

  • 多个文件资源合并成一个,减少 http 请求数
  • 支持模块化开发
  • 支持高级 JS 特性
  • 支持 Typescript、CoffeeScript 方言
  • 统一图片、CSS、字体等其它资源的处理模型
  • ...

使用

关于 Webpack 的使用方法,基本都围绕 配置 展开,而这些配置大致可划分为两类:

  • 流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项
  • 工具类:主流程之外,提供更多工程化能力的配置项

流程类配置

配置总览

Webpack 配置官方文档

demo

开始

文件结构:

  1. 声明入口 'entry'
  1. 声明出口 'ouyput'
  1. 运行 'npx webpack'

处理 CSS

文件结构:

index.js:

  1. 安装 Loader
  1. 添加 'module' 处理 CSS 文件

结果:

接入 Babel 处理 JS

文件结构:

index.js:

  1. 安装依赖:
  1. 声明产物出口 'output':
  1. 执行 'npx webpack':

生成 HTML

文件结构:

  1. 安装依赖(插件):
  1. 声明产物出口 'output':
  1. 执行 'npx webpack':

工具线

HMR

Hot Module Replacement —— 模块热替换

  1. 开启 HMR:
  1. 启动 Webpack:

HMR 原理

Tree-Shaking

Tree-Shaking:树摇,用于删除 Dead Code

Dead Code:

  • 代码没有被用到,不可到达
  • 代码的执行结果不会被用到
  • 代码只读不写
  • ...

开启 tree-shaking:

mode: "production"
optimization.usedExports: true

其他工具

  • 缓存
  • Sourcemap
  • 性能监控
  • 日志
  • 代码压缩
  • 分包
  • ...

理解 Loader

问题:

Webpack 只认识 JS:

为了处理非标准 JS 资源,设计出资源翻译模块 —— Loador,用于将资源翻译为标准 JS

使用 Loader

文件结构:

index.js:

  1. 安装 Loader:
  1. 添加 'module' 处理 css 文件:

链式调用

  • less-loader:实现less => css的转换
  • css-loader:将 CSS 包装成类似 module.exports = "${css}" 的内容,包装后的内容符合 JavaScript 语法
  • style-loader:将 css 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签

特性:

  • 链式执行
  • 支持异步执行
  • 分 normal、pitch 两种模式

编写 Loader

标准 Loader 需要具备的内容:

参考: Webpack 原理系列七:如何编写 loader

常见 Loader

理解插件

为什么要设计插件

这是一个特别复杂的过程;

  • 新人需要了解整个流程细节,上手成本高
  • 功能迭代成本高,牵一发动全身
  • 功能僵化,作为开源项目而言缺乏成长性

心智成本高 => 可维护性低 => 生命力弱

插件架构精髓:对扩展开放;对修改封闭

使用插件

安装 => 导入 => 创建实例:

demo

使用 html-webpack-plugin

使用 html-webpack-plugin + DefinePlugin

写插件

钩子

钩子:在编译的某个环节触发,某种程度上可以理解为 —— 事件

钩子的核心信息

  1. 时机:编译过程的特定节点。Webpack 会以钩子形式通知插件此刻正在发生什么事情;
  2. 上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信息;
  3. 交互:在上下文参数对象中附带了很多存在 side effect 的交互接口,插件可以通过这些接口改变。

demo:

  • 时机:compier.hooks.compilation
  • 参数:compilation
  • 交互:dependencyFactories.set

参考:Webpack 插件架构深度讲解