← 返回目录

第 2 卷

第 2 / 26 卷日期:

• 缓存复用无冗余下载:由于全局共享存储的存在,当某个包已被其他项目安装过(相同版本),后

• 无依赖冗余解析:pnpm 的非扁平依赖结构,无需像 npm/yarn 那样进行“依赖提升”和“冲突解

决”的复杂逻辑,解析依赖树的速度更快;同时,pnpm 采用并行安装机制,同时下载多个依赖包,进一步提升安装效率。

• 无需复制文件:传统包管理工具(npm/yarn/cnpm)安装时,会将包从缓存复制到项目

node_modules,而 pnpm 仅通过链接关联,无需执行文件复制操作,这是其安装速度远超其他工具的重要原因。

四、Webpack 基本工作原理与打包过程

  1. Webpack 基本工作原理

Webpack 是一个静态模块打包器(static module bundler),其核心工作原理是:在项目中,将所有资源(JavaScript、CSS、图片、字体等)都视为模块,通过入口文件(entry)递归解析所有模块

之间的依赖关系,然后通过 loader 转换非 JavaScript 模块(如 CSS 转成 JS 可处理的模块),再通过插件(plugin)完成额外的优化操作(如代码压缩、拆分),最终将所有依赖模块打包成一个或多

个静态资源文件(bundle),供浏览器加载使用。

核心核心思想:

  • 一切皆模块:资源文件(js/css/img 等)均可通过 import/require 导入,视为模块;
  • 依赖图谱:递归解析入口文件,构建所有模块的依赖关系图谱(dependency graph);
  • 转换器(loader):处理非 JS 模块,将其转为 Webpack 可识别的模块;
  • 扩展器(plugin):介入打包全流程,实现压缩、拆分、优化等复杂功能。
  1. Webpack 完整打包过程

Webpack 的打包过程分为三大阶段,每个阶段包含具体的执行步骤:

阶段一:初始化阶段(准备工作)

  1. 解析配置文件:Webpack 读取项目根目录的 webpack.config.js(或其他配置文件),结合

命令行参数(如 --mode production),合并生成最终的打包配置对象;

  1. 初始化 Compiler 实例:根据最终配置,创建 Webpack 的核心编译器实例(Compiler),

Compiler 负责统筹整个打包流程,生命周期钩子也基于该实例触发;

  1. 初始化插件:遍历配置中的 plugins 数组,执行插件的 apply 方法,将插件挂载到

Compiler 的生命周期钩子上,为后续打包过程做准备。

阶段二:编译阶段(构建依赖图谱+转换模块)

  1. 依赖递归收集:解析当前模块时,提取其中的 import/require 依赖声明,递归解析依赖的模

块,直到所有依赖都被解析完毕;

  1. 构建依赖图谱:在解析过程中,Webpack 会将所有模块及其依赖关系记录下来,形成一个完整的

依赖图谱(dependency graph),每个模块都有唯一的标识(module ID)。

阶段三:输出阶段(生成 bundle 文件)

  1. 模块分块:根据配置中的 optimization.splitChunks 等选项,将依赖图谱中的模块拆分到

不同的 chunk(代码块)中(如入口 chunk、第三方依赖 chunk、异步 chunk 等);

  1. 生成打包代码:对每个 chunk 进行处理,将模块代码拼接、封装(如生成 webpack_require

函数用于模块加载),转换为浏览器可运行的代码;

  1. 插件执行优化:在输出过程中,触发各类插件的生命周期钩子(如 TerserPlugin 压缩 JS 代

码、 MiniCssExtractPlugin 提取 CSS 为单独文件、 HtmlWebpackPlugin 生成 HTML 文件并引入 bundle);

  1. 输出文件:将处理后的 chunk 文件输出到配置中的 output.path 目录下,文件名遵循

output.filename 等配置规则,完成整个打包流程。

五、Webpack 生产环境打包优化配置

生产环境打包的核心目标是:减小 bundle 体积、提高代码运行效率、优化浏览器加载速度,具体配置方案如下:

  1. 基础配置优化

• 指定 mode 为 production:

这是最基础的优化, mode: 'production' 会自动启用 Webpack 内置的优化功能(如代码压缩、树摇、作用域提升等),无需手动配置。

Code block

1module.exports = { 2mode: 'production', // 生产环境模式

3entry: './src/index.js', 4output: {

5filename: '[name].[contenthash].js',//内容哈希,用于缓存优化
6path: path.resolve(__dirname, 'dist'),
7clean: true,//打包前清空dist目录
8}
9 }

• 启用树摇(Tree Shaking):

树摇用于删除项目中未被使用的代码(死代码),仅支持 ES 模块( import/export),需满足两个条件: mode: 'production' + 代码为 ES 模块(避免使用 CommonJS 模块)。

额外配置(可选,增强树摇效果):

Code block

1module.exports = { 2optimization: {

3usedExports: true,//标记未被使用的导出
4}
5 }

• 作用域提升(Scope Hoisting):

将多个小模块合并为一个大模块,减少函数声明和模块加载的开销,提高代码运行效率, mode:

'production' 自动启用,手动配置如下:

Code block

1module.exports = { 2optimization: {

3concatenateModules: true,//启用作用域提升
4}
5 }

• 代码分割(Code Splitting):

将大 bundle 拆分为多个小 bundle,实现按需加载(首屏加载更快),同时缓存复用(公共代码不重复加载),核心配置:

Code block

1module.exports = { 2optimization: {

3splitChunks: {

4chunks: 'all',//拆分所有类型的chunk(入口chunk +异步chunk)
5cacheGroups: {
6vendor: {//拆分第三方依赖(如react、vue)
7test: /[\\/]node_modules[\\/]/,
全站分卷索引 · 26 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷
  20. 20第 20 卷
  21. 21第 21 卷
  22. 22第 22 卷
  23. 23第 23 卷
  24. 24第 24 卷
  25. 25第 25 卷
  26. 26第 26 卷