Webpack 知识体系 | 青训营笔记

53 阅读5分钟

Webpack 知识体系 | 青训营笔记

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

课程简介

由浅入深,从应用技巧到组件开发,再到 Webpack 构建流程的基本原理剖析,最后总结一套学习方法论,帮助读者 0 基础搭建 Webpack 知识体系。

课前准备

安装浏览器

  1. 请下载安装最新版本 NodeJS 环境;
  2. 请下载安装一个「现代」浏览器,比如 ChromeFirefoxEdge 等。推荐使用最新版的 Chrome 浏览器。

安装编辑器

要进行前端开发,一个趁手的编辑器必不可少。强烈推荐使用 Visual Studio Code,如果你习惯使用其它编辑器也是可以的。

提前阅读

课前建议先充分了解 Webpack 的基本功能与作用,参考资料:Webpack 官网,建议根据官网文档手动搭建若干示例。

什么是 Webpack

前端项目由资源构成。

png jpg gif webp js ts css less vue jsx sass ...

可以手动管理这些资源(09 年以前),在 HTML 中引用链接。

但这种管理方式:

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

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

直到出现了很多工程化工具。某种程度上正是这些工具的出现,才有了‘前端工程’这一概念。

概念

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

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

使用 Webpack

示例

  1. 安装
npm i -D webpack webpack-cli
  1. 编辑配置文件

webpack.config.js

module.exports = {
  entry: 'main.js',
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "./dist"),
  }
  module: {
    rules:[{
      test: /\.less$/i,
      use: ['style-loader', 'css-loader', 'less-loader']
    }]
  }
}
  1. 执行编译命令
npx webpack

核心流程

极度简化版:

  1. 入口处理 Get Start

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

  1. 依赖解析 Dependencies Lookup

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

  1. 资源解析 Transform

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

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

  1. 资源合并打包 Combine Assets

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

模块化 + 一致性

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

如何使用

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

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

流程类配置

  1. 输入

    • `entry`
    • `context`
  2. 模块解析

    • `resolve`
    • `externals`
  3. 模块转译

    • `module`
  4. 后处理

    • `optimization`
    • `mode`
    • `target`

配置总览

使用频率:

  • entry/output
  • module/plugins
  • mode
  • watch/devServer/devtool

Pasted image 20220810112540.png

Webpack 配置官方文档

处理 CSS

文件结构

.
|---src
|   |---index.js
|   |---index.css
|---webpack.config.js

index.js

const styles = require('./index.css');
// or
import styles from './index.css'
  1. 安装 Loader
npm add -D css-loader style-loader
  1. 添加 `module` 处理 CSS 文件

webpack.config.js

const path = require("path");

module.exports = {
  entry: './src/index',
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "./dist"),
  }
  module: {
    // css processor
    rules:[{
      test: /\.css/i,
      use: [
	    'style-loader', 
	    'css-loader',
      ],
    }],
  },
};

Pasted image 20220810113510.png

接入 Babel

文件结构

.
|---src
|   |---index.js
|---webpack.config.js

index.js

class Person {
    constructor() {
        this.name = 'Tecvan'
    }
}

console.log((new Person()).name)

const say = () => {}
  1. 安装依赖
npm i -D @babel/core @babel/preset-env babel-loader
  1. 声明产物出口 output

  2. 执行 npx webpack

const path = require("path");

module.exports = {
  entry: './src/index',
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "./dist"),
  }
  module: {
    rules:[{
      test: /\.js$/,
      use: [{
        loader: 'babel-loader',
        options: {
          presents: [
            [
              '@babel/preset-env'
            ]
          ]
        }
      }, ],
    }],
  },
};

Pasted image 20220810114847.png

生成 HTML

文件结构

.
|---src
|   |---index.js
|---webpack.config.js
  1. 安装依赖
npm i -D html-webpack-plugin
  1. 声明产物出口 ouput
const path = require("path");
const HtmlWebpackPlungin = require('html-webpack-plungin');

module.exports = {
  entry: './src/index',
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "./dist"),
  }
  plungin: [new HtmlWebpackPlugin()]
};
  1. 执行 npx webpack

HMR

Hot Module Replacement 模块热替换

  1. 开启 HMR

webpack.config.js

module.exports = {
  // ...
  devServer: {
    hot: true
  }
};
  1. 启动 Webpack
npx webpack serve

Pasted image 20220810121123.png

Webpack 原理系列十:HMR 原理全解析

Tree-Shaking

树摇,用于删除 Dead Code

Pasted image 20220810121558.png

Dead Code:

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

Tree-Shaking

  • 模块导出了,但未被其他模块使用

Pasted image 20220810121608.png

开启 tree-shaking:

  • mode: "production"
  • optimization.usedExports: true

PS:对工具类库如 Lodash 有奇效

其他工具

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

理解 Loader

Webpack 只认识 JS

为了处理非标准 JS 资源,设计出资源翻译模块 —— Loader

用于将资源翻译为标准 JS

Pasted image 20220810121929.png

Pasted image 20220810121958.png

链式调用

module.exports = {
  module: {
    rules:[{
      test: /\.less%/i,
      use: [
	    'style-loader', 
	    'css-loader',
	    'less-loader',
      ],
    }],
  },
};

Pasted image 20220810122039.png

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

其他特性

Pasted image 20220810122139.png

特点:

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

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

常见 Loader

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

Pasted image 20220810122706.png

理解插件

Pasted image 20220810122939.png

这是一个特别复杂的过程,那么:

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

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

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

甚至,Webpack 本身的很多功能也是基于插件实现的

hook

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

hook 的核心信息:

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

Pasted image 20220810123517.png

时机:compier.hooks.compilation

参数:compilation ...

交互:dependencyFactories.set

Pasted image 20220810123621.png

Webpack 插件架构深度讲解

一文吃透 Webpack 核心原理

学习方法

  1. 入门应用
  • 理解打包流程
  • 熟练掌握常用配置项、Loader、插件的使用方法,能够灵活搭建集成 Vue、React、Babel、Less、Sass、图片处理等工具的 Webpack 环境
  • 掌握常见脚手架工具的用法,例如:Vue-cli、creat-react-app、@angular/cli
  1. 进阶
  • 理解 Loader、Plugin 机制,能够自行开发 Webpack 组件
  • 理解常见性能优化手段,并能用于解决实际问题
  • 理解前端工程化概念与生态现状
  1. 大师级
  • 阅读源码,理解 Webpack 编译、打包原理,甚至能够参与共建

Pasted image 20220810124136.png

课后阅读材料