什么是 webpack

是一个静态打包工具

核心思想是:静态分析模块之间的依赖关系,然后将这些模块按一定规则打包成一个或多个文件

解决了以下问题:

  • 代码模块化和统一管理
  • 自动处理各模块的依赖
  • 热更新,提高开发效率
  • 代码拆分、压缩等

构建流程

初始化配置 从 entry 开始分析模块依赖 通过 loader 进行各个文件的编译 build 完成输出到 dist 目录

Loader

是什么:

Webpack 中的文件加载器,是一个函数。运行在打包文件之前。

作用:

Webpack 本身默认只能理解处理 .js.json 文件,Loader 的作用是让 Webpack 能够处理其他类型的文件,通过链式调用对资源文件进行转换和处理

使用:

写在 module.rules 属性中,常见的有:

  • css-loader:用于加载 css
  • style-loader:用于将 css 添加到 DOM 中的 <style> 标签中
  • sass-loader:处理 sass 文件
  • file-loader:将文件打包到输出目录中
  • url-loader:将文件转换为内联的 base64

Plugin

是什么:

Webpack 中的插件,是一个具有 apply 方法的对象。在整个编译周期都起作用。webpack 通过 Tapable框架 在生命周期中的各个环节提供钩子 (hook) 事件,Plugin 通过监听钩子事件在 apply 方法的入参的钩子上做额外操作,进而拓展 webpack 的功能。

  1. 一个 Class,在类中定义一个 apply 方法
  2. 指定一个绑定到 webpack 自身的事件钩子
  3. 处理 webpack 内部实例的特定数据

作用:

用于对 Webpack 的构建流程进行功能扩展

使用:

写在 plugins 属性中,常见的有:

  • HtmlWebpackPlugin:打包结束后,⾃动生成⼀个 html 文件,并把打包生成的 js 模块引⼊到该 html 中
  • CleanWebpackPlugin:构建前清理输出目录,避免旧文件残留
  • TerserWebpackPlugin:压缩 JS 代码
  • webpack-bundle-analyzer:打包文件分析
  • MiniCssExtractPlugin:分离 CSS 为独立文件,支持按需加载

Loader 和 Plugin 区别

特性LoaderPlugin
主要作用转换文件内容(如转译、预处理)扩展构建流程(优化、资源管理、注入环境变量等)
执行时机在模块加载时(文件转换为模块时)在整个构建生命周期(从初始化到输出)的各个阶段
配置方式通过 module.rules 数组配置通过 plugins 数组配置(需要 new 实例化)
典型场景处理 JS/CSS/图片等文件转译生成 HTML、压缩代码、提取 CSS 等全局操作
依赖关系针对特定文件类型(如 .scss )不依赖文件类型,可干预整个构建流程

tree-shaking

一种代码静态分析技术,用于消除 JavaScript 应用中的未使用代码(Dead Code)。通过移除这些未使用的代码,可以减少最终打包文件的体积,从而提高应用的加载速度和性能

原理

静态分析:依赖 ES6 Module 功能(不能是 CommonJS 因为是它动态的运行时加载)

开启步骤

  1. 关闭 babel 的模块语法转换
  2. 在 @babel/preset-env 配置中 modules 设置为 false,这样 babel 就不会将我们写的 es6 Module 的导入方式进行转换(tree-shaking 依赖 es6 的 Module 语法)
  3. 设置 mode 为 production
  4. 确保 usedExports 为 true(默认为 true)
  5. 必要的情况下指定 sideEffects

实践

  • usedExports:开启后会标记哪些代码没有被使用,之后通过 Terser 来进行优化
  • sideEffects:在 package.json 中配置哪些文件不进行优化,告诉 webpack 哪些模块有副作用(代码会执行一些特殊的逻辑如定义全局变量等,不能仅仅通过 export 来判断这段代码的使用),避免被错误删除

提高构建速度

  • 给一些常用的路径起别名,减少查找过程
  • 使用 SplitChunksPlugin 代码分割,将公共代码抽取出来,减少重复打包
  • 使用缓存(使用 cache 配置项,可以将文件序列化到硬盘中)
  • 配置多线程并行构建