Webpack 知识体系|青训营笔记

109 阅读7分钟

这是我参与「第四届青训营 」笔记创作活动的的第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 资源管理模型不一致

image.png

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

  • 示例

    1. 安装:npm i -D webpack webpack-cli
    2. 编辑配置文件 image.png
    3. 执行编译命令:npx webpack
      打包后的部分 main.js 代码: image.png
  • 核心流程 —— 极度简化版 image.png

  • 模块化 + 一致性
    Webpack 本质上就做了两件事情:模块化 + 一致性。
    模块化:支持对不同类型的资源都用 import 、 require 这些语句去管理这些资源。

    • 多个文件资源合并成一个,减少 http 请求数
    • 支持模块化开发
    • 支持高级 JS 特性
    • 支持 TypeScript 、 CoffeeScript 方言
    • 统一图片、 CSS 、字体等其它资源的处理模型
    • Etc……
  • 使用 Webpack 关于 Webpack 的使用方法,基本都围绕“配置”展开,而这些配置大致都可划分为两类:

    • 流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项(以下是部分配置项) image.png

    • 工具类:主流程之外,提供更多工程化能力的配置项。

      配置总览: image.png Webpack 配置官方文档

  • 使用 Webpack
    文件结构:
    image.png

    1. 声明入口 entry
      image.png
    2. 声明产物出口 output
      image.png
    3. 运行 npm webpack
  • 处理 CSS
    文件结构:
    image.png

    1. 安装 Loader :npm add -D css-loader style-loader
    2. 添加 module 处理 css 文件 image.png
  • 接入 Babel
    文件结构:
    image.png

    1. 安装依赖:npm i -D @babel/core @babel/preset-env babel-loader
    2. 声明产物出口 output
      image.png
    3. 执行: npx weboack
  • 生产 HTML 文件结构:
    image.png

    1. 安装依赖:npm i -D html-webpack-plugin
    2. 声明产物出口 output
      image.png
    3. 执行: npx weboack image.png
  • 工具线具体的用法 —— HMR (Hot Module Replacement ,模块热替换,写的代码能够立刻被更新到浏览器上并且浏览器是不需要刷新的) image.png Webpack 原理系列十:HMR 原理全解析

    • 开启 HMR
      image.png
    • 启动 Webpack :npx webpack serve
  • 工具线具体的用法 —— Tree-Shaking
    Tree-Shaking 是树摇,本质上是用于删除一些 Dead Code (没有用到的代码)。
    Dead Code :

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

    Tree-Shaking :模块导出了,但未被其它模块使用。 image.png 开启 Tree-Shaking :

    1. "mode": "production"
    2. "optimization.usedExports": true
  • 其它工具

    • 缓存
    • sourcemap
    • 性能监控
    • 日志
    • 压缩代码
    • 分包
    • ……

进阶篇:理解 Loader

loader 核心功能:把非 JS 的资源转换成 JS 的资源。

  • 使用 Loader

    1. 安装 Loader :npm add -D css-loader style-loader less-loader
    2. 添加 module 处理 css 文件
      image.png
  • 认识 Loader :链式调用

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


      image.png Loader 它在运行时会一个一个的逐步的去执行每一个 loader ,这是 Webpack 的运行机制。
  • 认识 Loader :其它特性 image.png 在运行一开始的时候会有一个 pitch 阶段,在 pitch 阶段会有一个特性就是任意一个 loader 的 pitch 阶段有返回值的话它就会停止后面的执行,这特性特别适合用来做一些 catch 。
    执行阶段结束会变成标准的 JavaScript 代码。
    特点:

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

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

  • 常见 Loader 站在使用角度,建议掌握这些常见 Loader 的功能、配置方法 image.png


进阶篇:理解 Plugin

很多知名工具(VS Code 、 Chrome 、 Babel 、 Vue)都设计了所谓“插件”架构,为什么?
因为可以能提升整个应用的扩展性或者说工具的扩展性。 image.png Webpack 的源码、主流层次非常非常的复杂,那么:

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

心智成本高 => 可维护性低 => 生命力弱
插件架构精髓就是对扩展开放,对修改关闭的思维(只做最核心的那一部分,但是开放一系列的扩展方式、修改方式)。

  • 首先:插件围绕“钩子”展开 image.png 钩子某种程度上可以理解为一个事件,但是这个事件会比普通的事件复杂一点。
    钩子的核心信息(复杂一点):
  1. 时机:编译过程的特定节点, Webpack 会以钩子形式通知插件此刻正在发生什么事情;
  2. 上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信息;
  3. 交互:在上下文参数对象中附带了许多存在 side effect 的交互接口,插件可以通过这些接口改变。

简化、关键的钩子: image.png

image.png 时机:"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 编译、打包原理,甚至能够参与共建

image.png