Webpack的分包策略面试题

一、什么是 Webpack 的代码分割?有什么好处?有哪些策略?

1. 核心思路(一句话)

代码分割就是把原本需要一起加载的模块拆成多个 Chunk,让"首屏必需代码"和"非首屏代码"按需加载,同时把稳定的公共代码独立出来,从而减少首屏资源、提高缓存复用率。


二、先搞清楚几个核心概念

这是这道题最容易混淆的地方。

text 复制代码
源代码模块
   │
   │ Webpack 构建
   ▼
Module
   │
   │ 根据入口、动态 import、SplitChunks 等进行组织
   ▼
Chunk
   │
   │ 经过编译、压缩、代码生成
   ▼
Asset
   │
   ▼
最终输出的 JS / CSS / 图片等文件

Module、Chunk、Bundle、Asset 不要混为一谈

概念 含义
Module 源代码中的模块,例如 react、App.js
Chunk Webpack 根据依赖关系组织出来的一组模块
Bundle 通常泛指最终输出的代码包,实际开发中经常泛称输出文件
Asset 最终生成的资源,例如 main.js、vendors.js、lazy.js

面试重点:

代码分割本质上是 Chunk 层面的拆分,最终表现为多个资源文件。

所以不要简单说:

"Webpack 把一个 bundle 文件拆成几个文件。"

更准确的是:

Webpack 根据入口、动态 import() 和代码分割策略,把模块图划分成多个 Chunk,再生成多个资源文件。


三、为什么需要代码分割?

主要矛盾

主要矛盾:首屏不应该加载暂时用不到的代码

假设一个后台系统:

text 复制代码
整个应用
├── 登录
├── 首页
├── 用户管理
├── 商品管理
├── 订单管理
├── 数据分析
├── 富文本编辑器
└── 图表库

如果全部打进首屏:

text 复制代码
main.js
├── React
├── React Router
├── 图表库
├── 富文本编辑器
├── 用户管理
├── 商品管理
├── 订单管理
├── 数据分析
└── 首页

用户只是打开首页,却下载了:

text 复制代码
首页需要的代码
+
暂时不需要的代码
+
大量第三方依赖

于是:

text 复制代码
JS 体积大
   ↓
下载时间增加
   ↓
解析 / 编译 / 执行时间增加
   ↓
主线程压力增加
   ↓
页面交互变慢

次要矛盾:缓存复用率低

假设:

text 复制代码
main.js
├── React
├── React Router
├── 公共工具
├── 首页
├── 用户页面
└── 商品页面

这次只修改:

text 复制代码
商品页面

重新构建以后:

text 复制代码
main.js → 内容发生变化

如果使用内容哈希:

text 复制代码
main.abc123.js
        ↓
        修改
        ↓
main.def456.js

那么原来的整个 main.js 不能直接复用。

如果合理拆分:

text 复制代码
vendors.hash.js
runtime.hash.js
home.hash.js
user.hash.js
product.hash.js

修改商品页面:

text 复制代码
vendors.hash.js   不变
runtime.hash.js   不变
home.hash.js      不变
user.hash.js      不变
product.hash.js   变化

浏览器就可以继续复用其他资源。


四、代码分割解决方案流程图

text 复制代码
                     Webpack 构建
                          │
                          ▼
                    分析模块依赖图
                          │
             ┌────────────┼────────────┐
             │            │            │
             ▼            ▼            ▼
          多入口       动态 import()   SplitChunks
             │            │            │
             ▼            ▼            ▼
         多个入口       异步 Chunk     公共 Chunk
             │            │            │
             └────────────┼────────────┘
                          ▼
                    Chunk 合理拆分
                          │
                          ▼
                多个 JS / CSS Asset
                          │
             ┌────────────┴────────────┐
             ▼                         ▼
        首屏只加载必要代码          非首屏按需加载
             │                         │
             └────────────┬────────────┘
                          ▼
                    性能 + 缓存优化

五、Webpack 常见代码分割策略

实际面试建议记住 4 类。

text 复制代码
Webpack 代码分割
│
├── 1. 多入口 Entry
│
├── 2. 动态 import()
│
├── 3. SplitChunksPlugin
│
└── 4. Runtime Chunk

其中:

动态 import() 解决"什么时候加载";SplitChunksPlugin 解决"公共代码怎么拆"。

这是非常重要的区分。


六、第一种:多入口分包

核心思路

不同入口本身代表不同的应用入口,Webpack 可以根据入口形成不同的 Chunk。

例如:

text 复制代码
后台管理系统
├── admin
└── mobile

配置:

js 复制代码
const path = require("path");

module.exports = {
  mode: "production",

  entry: {
    admin: "./src/admin.js",
    mobile: "./src/mobile.js",
  },

  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[contenthash:8].js",
    clean: true,
  },
};

最终可能得到:

text 复制代码
dist/
├── admin.a1b2c3d4.js
└── mobile.e5f6g7h8.js

访问后台:

text 复制代码
/admin

只需要:

text 复制代码
admin.js

访问移动端:

text 复制代码
/mobile

只需要:

text 复制代码
mobile.js

适用场景

适合:

text 复制代码
多页面应用
多端应用
管理后台 + 官网
PC + Mobile
不同业务入口

边界问题

如果两个入口大量依赖相同模块:

text 复制代码
admin
 ├── React
 └── lodash

mobile
 ├── React
 └── lodash

可能出现:

text 复制代码
admin.js
 └── React + lodash

mobile.js
 └── React + lodash

导致重复打包。

所以通常还需要:

text 复制代码
SplitChunksPlugin

提取公共依赖。


七、第二种:动态 import()------SPA 最重要的代码分割方式

核心思路

动态 import() 是天然的异步边界,Webpack 会把它后面的模块构建成异步 Chunk,在真正执行到这里时再加载。

例如:

js 复制代码
// src/router.js

export async function loadUserPage() {
  // 动态 import() 会告诉 Webpack:
  // UserPage 不需要跟当前主入口一起加载,
  // 可以作为一个异步 Chunk 单独输出。
  const module = await import("./UserPage.js");

  // 动态 import() 返回的是一个 Promise,
  // Promise fulfilled 后才能拿到真正的模块。
  return module.default;
}

Webpack 可能生成:

text 复制代码
main.js
UserPage.xxxxx.js

加载关系:

text 复制代码
浏览器打开页面
      │
      ▼
   main.js
      │
      │ 用户进入用户页面
      ▼
执行 import("./UserPage.js")
      │
      ▼
Webpack Runtime
      │
      ▼
请求 UserPage.xxxxx.js
      │
      ▼
加载完成
      │
      ▼
执行 UserPage

八、React 路由懒加载就是这个原理

例如:

jsx 复制代码
import { lazy, Suspense } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

// React.lazy 底层依赖的就是动态 import()。
// UserPage 不会和首页代码强制打在同一个初始 Chunk 中。
const UserPage = lazy(() => import("./pages/UserPage"));
const OrderPage = lazy(() => import("./pages/OrderPage"));

function App() {
  return (
    <BrowserRouter>
      {/* 动态 Chunk 加载期间显示 loading */}
      <Suspense fallback={<div>页面加载中...</div>}>
        <Routes>
          <Route path="/user" element={<UserPage />} />
          <Route path="/order" element={<OrderPage />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

export default App;

最终:

text 复制代码
初始加载
│
├── main.js
└── 首页需要的代码

进入 /user
│
└── UserPage.xxx.js

进入 /order
│
└── OrderPage.xxx.js

这就是 SPA 中非常典型的路由级代码分割。


九、第三种:SplitChunksPlugin------实际项目非常重要

Webpack 提供:

js 复制代码
optimization.splitChunks

用于从多个 Chunk 中识别和提取公共模块。

例如:

text 复制代码
pageA
 ├── React
 ├── lodash
 └── A业务代码

pageB
 ├── React
 ├── lodash
 └── B业务代码

如果不合理拆分:

text 复制代码
pageA.js
 ├── React
 ├── lodash
 └── A

pageB.js
 ├── React
 ├── lodash
 └── B

公共代码重复。通过 SplitChunks:

text 复制代码
vendors.js
├── React
└── lodash

pageA.js
└── A

pageB.js
└── B

于是:

text 复制代码
公共代码 → 单独缓存
业务代码 → 独立变化

十、完整 SplitChunks 配置示例

js 复制代码
const path = require("path");

module.exports = {
  mode: "production",

  entry: {
    main: "./src/main.js",
  },

  output: {
    path: path.resolve(__dirname, "dist"),

    // [name]:Chunk 名称
    // [contenthash]:根据最终内容生成哈希
    // 内容不变时,文件名也尽可能保持稳定,从而提高缓存命中率。
    filename: "[name].[contenthash:8].js",

    // 动态 import() 产生的异步 Chunk 使用这个命名规则。
    chunkFilename: "[name].[contenthash:8].chunk.js",

    clean: true,
  },

  optimization: {
    splitChunks: {
      // async:只处理异步加载的 Chunk。
      // initial:处理初始 Chunk。
      // all:初始 Chunk 和异步 Chunk 都处理。
      chunks: "all",

      // 只有模块被至少两个 Chunk 共同使用时,
      // 才考虑把它提取出来。
      minChunks: 2,

      // 防止拆出来的 Chunk 太小,造成大量网络请求。
      minSize: 20000,

      cacheGroups: {
        // 第三方依赖通常来自 node_modules。
        vendors: {
          test: /[\\/]node_modules[\\/]/,

          // 设置较高优先级,
          // 优先把第三方依赖提取出来。
          priority: 10,

          // 多个入口/异步 Chunk 可以复用这个公共 Chunk。
          reuseExistingChunk: true,

          name: "vendors",
        },

        // 自己的公共业务代码。
        common: {
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
          name: "common",
        },
      },
    },
  },
};

这里需要理解:

text 复制代码
动态 import()
        │
        ▼
产生异步 Chunk
        │
        ▼
SplitChunksPlugin
        │
        ├── 判断是否存在公共模块
        │
        ├── 判断模块使用次数
        │
        ├── 判断 Chunk 大小
        │
        └── 根据 cacheGroups 决定如何提取
                │
                ▼
        公共 Chunk / Vendor Chunk

十一、第四种:Runtime Chunk

Webpack 生成的代码中有一部分不是业务代码,而是:

text 复制代码
模块加载机制
Chunk 加载机制
模块映射关系
动态 import() 相关运行时代码

例如:

text 复制代码
main.js
├── 业务代码
├── 第三方依赖
└── Webpack Runtime

可以进一步拆成:

text 复制代码
runtime.js
main.js
vendors.js

Webpack 配置:

js 复制代码
module.exports = {
  optimization: {
    runtimeChunk: "single",
  },
};

形成:

text 复制代码
runtime.js
vendors.js
main.js

十二、为什么 Runtime 单独拆出来?

重点不是"Runtime 很大"。

恰恰相反:

Runtime 通常比较小,但它可能随着 Chunk 结构变化而发生变化。

例如:

text 复制代码
runtime.js
   │
   └── 保存 Chunk / 模块加载相关映射信息

如果业务代码发生变化:

text 复制代码
main.js → 变化

可能导致:

text 复制代码
runtime.js → 也变化

如果把 Runtime 独立出来,可以改善长期缓存策略。

但是:

Runtime 分包不是首屏优化的核心手段,主要价值是缓存隔离和 Chunk 管理。

所以优化价值通常不是很大。


十三、真正的分包策略应该怎么设计?

不要机械地:

text 复制代码
一个页面 = 一个 Chunk

也不要:

text 复制代码
一个模块 = 一个 Chunk

真正应该按照:

text 复制代码
加载边界
+
业务边界
+
缓存边界
+
复用关系

来设计。


推荐架构

text 复制代码
                  应用代码
                     │
          ┌──────────┴──────────┐
          │                     │
       首屏代码               非首屏代码
          │                     │
          │                dynamic import()
          │                     │
          ▼                     ▼
      main Chunk             async Chunk
          │                     │
          └──────────┬──────────┘
                     ▼
              SplitChunksPlugin
                     │
          ┌──────────┴──────────┐
          ▼                     ▼
      第三方公共代码          业务公共代码
       vendors.js             common.js
          │
          ▼
       Runtime
          │
          ▼
       runtime.js

十四、分包不是越细越好

这是面试中的一个高级边界问题。

很多人会说:

"分包以后文件越小越好。"

这是错误的。

例如:

text 复制代码
main.js
a.js
b.js
c.js
d.js
e.js
f.js
g.js
h.js

可能出现:

text 复制代码
HTTP 请求数量增加
        ↓
请求调度成本增加
        ↓
Chunk 加载关系复杂
        ↓
JS 解析 / 执行碎片化
        ↓
整体性能反而下降

所以真正目标是:

合理拆分,而不是无限拆分。


十五、什么时候适合分包?

场景一:路由级分包

最典型。

text 复制代码
首页
用户
订单
商品
数据分析

用户通常不会同时访问所有页面。

因此:

text 复制代码
首页 → 首屏加载
用户 → 进入用户页面再加载
订单 → 进入订单页面再加载
商品 → 进入商品页面再加载
数据分析 → 进入数据分析页面再加载

场景二:大型第三方库

例如:

text 复制代码
ECharts
Monaco Editor
富文本编辑器
PDF Viewer
地图 SDK

如果首页根本用不到:

js 复制代码
const Editor = lazy(() => import("./Editor"));

不要把几十 MB 的编辑器代码直接塞进首屏。


场景三:低频功能

例如:

text 复制代码
设置
高级搜索
报表
帮助中心
管理功能

这些功能访问频率较低,非常适合异步加载。


十六、边界场景:哪些代码不应该随便拆?

例如:

text 复制代码
React
ReactDOM
核心 UI 框架
首屏必须使用的公共组件
首屏核心业务代码

如果这些代码拆得过度:

text 复制代码
main.js
  ↓
请求 React
  ↓
请求 ReactDOM
  ↓
请求 UI
  ↓
请求业务

可能反而增加加载成本。

因此:

首屏强依赖、体积合理、复用率高的代码,通常应该保留在合理的初始 Chunk 或公共 Chunk 中。


十七、代码分割和懒加载不是一回事

这是非常容易被问到的追问。

代码分割

解决:

代码怎么拆。

懒加载

解决:

代码什么时候加载。

动态:

js 复制代码
import("./UserPage");

同时完成:

text 复制代码
代码分割
+
延迟加载

但是两者概念不同。


十八、代码分割和缓存优化的关系

可以用一句话记忆:

代码分割负责建立缓存边界,内容哈希负责让这个缓存边界长期稳定。

例如:

text 复制代码
vendors.abc123.js
common.def456.js
home.ghi789.js
user.jkl012.js

修改:

text 复制代码
user.js

理想结果:

text 复制代码
vendors.abc123.js   ← 不变
common.def456.js    ← 不变
home.ghi789.js      ← 不变
user.xxx999.js      ← 变化

浏览器:

text 复制代码
vendors → 命中缓存
common  → 命中缓存
home    → 命中缓存
user    → 下载新版本

这才是分包带来的长期缓存价值。


十九、分包完整实现示例

下面给一个比较接近真实项目的 Webpack 配置:

js 复制代码
const path = require("path");

module.exports = {
  mode: "production",

  // 一个 SPA 只有一个主入口。
  entry: {
    main: "./src/main.js",
  },

  output: {
    path: path.resolve(__dirname, "dist"),

    // 初始 Chunk 的文件名。
    // contenthash 根据最终内容生成,
    // 内容不变时可以尽可能复用浏览器缓存。
    filename: "[name].[contenthash:8].js",

    // 动态 import() 产生的异步 Chunk 使用这个文件名。
    chunkFilename: "[name].[contenthash:8].chunk.js",

    clean: true,
  },

  optimization: {
    /*
     * 将 Webpack Runtime 单独提取。
     *
     * Runtime 负责模块/Chunk 的加载管理,
     * 与业务代码隔离以后,有利于长期缓存。
     */
    runtimeChunk: "single",

    /*
     * 公共代码提取。
     */
    splitChunks: {
      /*
       * all:
       * 同时处理初始 Chunk 和异步 Chunk。
       */
      chunks: "all",

      /*
       * 一个模块至少被两个 Chunk 使用,
       * 才考虑把它提取成公共 Chunk。
       */
      minChunks: 2,

      /*
       * 避免产生大量过小的 Chunk。
       */
      minSize: 20000,

      cacheGroups: {
        /*
         * 第三方依赖。
         *
         * 例如:
         * React
         * ReactDOM
         * React Router
         * lodash
         */
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendors",

          // 第三方依赖优先提取。
          priority: 10,

          // 如果已经存在合适的 Chunk,则尽量复用。
          reuseExistingChunk: true,
        },

        /*
         * 项目自己的公共业务代码。
         */
        common: {
          minChunks: 2,
          name: "common",
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    },
  },
};

业务代码:

jsx 复制代码
import { lazy, Suspense } from "react";

/*
 * 首页属于首屏核心功能,
 * 因此直接进入初始 Chunk。
 */
import HomePage from "./pages/HomePage";

/*
 * 用户页面属于非首屏功能。
 *
 * 动态 import() 建立异步边界,
 * Webpack 会把 UserPage 构建为异步 Chunk。
 */
const UserPage = lazy(() => import("./pages/UserPage"));

/*
 * 订单页面同样进行路由级代码分割。
 */
const OrderPage = lazy(() => import("./pages/OrderPage"));

function App() {
  const path = window.location.pathname;

  /*
   * 首页:
   * 直接使用已经加载的 HomePage。
   */
  if (path === "/") {
    return <HomePage />;
  }

  /*
   * 用户页和订单页:
   * 进入页面以后才加载对应 Chunk。
   */
  if (path === "/user") {
    return (
      <Suspense fallback={<div>用户页面加载中...</div>}>
        <UserPage />
      </Suspense>
    );
  }

  if (path === "/order") {
    return (
      <Suspense fallback={<div>订单页面加载中...</div>}>
        <OrderPage />
      </Suspense>
    );
  }

  return <div>404</div>;
}

export default App;

最终可能形成:

text 复制代码
dist/
│
├── runtime.xxxxxxxx.js
│
├── vendors.xxxxxxxx.js
│
├── common.xxxxxxxx.js
│
├── main.xxxxxxxx.js
│
├── UserPage.xxxxxxxx.chunk.js
│
└── OrderPage.xxxxxxxx.chunk.js

二十、Webpack 分包底层原理

这是面试官继续追问时真正需要讲的。

text 复制代码
源代码
  │
  ▼
Webpack 从 Entry 开始
  │
  ▼
递归解析 import
  │
  ▼
建立 Module Graph
  │
  ▼
根据依赖关系形成 Chunk Graph
  │
  ├── Entry → Initial Chunk
  │
  ├── dynamic import() → Async Chunk
  │
  └── SplitChunks → 公共 Chunk
  │
  ▼
Runtime 管理 Chunk 加载
  │
  ▼
代码生成
  │
  ▼
Asset
  │
  ▼
main.js / vendors.js / xxx.chunk.js

二十一、动态 import() 为什么真的可以做到"进入页面才加载"?

关键不是 JavaScript 自己"神奇地延迟执行"。

而是:

js 复制代码
import("./UserPage");

在 Webpack 构建阶段被识别为:

text 复制代码
异步依赖边界

Webpack:

text 复制代码
UserPage
   ↓
独立 Chunk
   ↓
UserPage.xxx.js

运行时:

text 复制代码
执行 import()
      ↓
Webpack Runtime
      ↓
发现目标 Chunk 尚未加载
      ↓
创建 script 标签
      ↓
请求 UserPage.xxx.js
      ↓
Chunk 下载完成
      ↓
注册模块
      ↓
Promise resolve
      ↓
继续执行

因此:

动态 import() 的核心是"构建阶段形成异步 Chunk,运行阶段通过 Webpack Runtime 按需加载这个 Chunk"。


二十二、如何判断自己的分包是否合理?

不要凭感觉。

应该结合:

text 复制代码
Bundle Analyzer
+
Chrome Performance
+
Lighthouse
+
真实用户性能数据

重点观察:

text 复制代码
1. 首屏 JS 体积
2. 初始请求数量
3. JS 下载时间
4. JS Parse / Compile 时间
5. JS 执行时间
6. Chunk 重复率
7. 缓存命中率
8. 路由切换时的 Chunk 加载情况

例如:

text 复制代码
修改一个按钮
      ↓
发现 vendors.hash.js 也变化
      ↓
说明公共 Chunk 的缓存边界可能不稳定
      ↓
检查模块拆分、依赖关系、构建配置

二十三、这道题的主要矛盾和次要矛盾

主要矛盾

首屏加载什么代码

这是代码分割最核心的问题:

text 复制代码
首屏真正需要的代码
            ↓
       尽快加载
            ↓
非首屏代码
            ↓
       延迟加载

次要矛盾

1. 公共代码复用

text 复制代码
多个 Chunk 共用
       ↓
提取公共 Chunk

2. 长期缓存

text 复制代码
稳定模块
   ↓
稳定 Chunk
   ↓
contenthash
   ↓
浏览器长期缓存

3. 请求数量

text 复制代码
不能无限拆分

4. Chunk 大小

text 复制代码
不能太大
也不能太碎

二十四、这道题最容易踩的坑

错误 1

Webpack 默认只有一个 bundle。

更准确:

Webpack 可以根据入口、动态 import() 和优化策略生成一个或多个 Chunk / Asset。


错误 2

分包一定能提高首屏性能。

不准确。

正确:

合理的代码分割可以减少首屏必须下载、解析和执行的 JavaScript,但过度分割也可能增加请求和运行时开销。


错误 3

分包就是一个页面一个文件。

错误。

应该按照:

text 复制代码
加载边界
业务边界
公共依赖
缓存边界

综合决定。


错误 4

动态 import() 只是异步加载。

不完整。

它同时是:

text 复制代码
构建阶段:
异步 Chunk 边界

运行阶段:
按需加载 Chunk

错误 5

Runtime 分包主要是为了减小文件体积。

不准确。

更主要的是:

隔离 Webpack Runtime,使业务 Chunk 变化时尽量不影响其他长期缓存资源。


错误 6

只要使用动态 import() 就不需要 SplitChunks。

错误。

两者解决的问题不同:

text 复制代码
dynamic import()
      ↓
哪里建立异步边界?

SplitChunks
      ↓
公共模块怎么提取?

二十五、面试回答的结构化逻辑

建议你以后遇到这道题直接按照:

text 复制代码
① 是什么
   ↓
代码分割 = 合理划分 Chunk

② 为什么
   ↓
首屏代码减少
   +
缓存边界更稳定

③ 怎么做
   ↓
多入口
+
动态 import()
+
SplitChunks
+
Runtime Chunk

④ 怎么设计
   ↓
首屏 / 非首屏
公共依赖
业务公共代码
缓存边界

⑤ 有什么坑
   ↓
不能过度分割
不能只看文件数量
需要结合性能数据分析

二十六、满分答案

Webpack 的代码分割,本质是把模块合理划分成多个 Chunk,让首屏只加载必要代码,非首屏代码按需加载,同时把公共代码独立出来,从而降低首屏加载成本、提高缓存复用率。

一、整体流程

text 复制代码
源代码
  │
  ▼
Webpack 分析 Module Graph
  │
  ▼
划分 Chunk
  │
  ├── 多入口 Entry
  ├── 动态 import() → 异步 Chunk
  └── SplitChunks → 公共 Chunk
  │
  ▼
Runtime 管理 Chunk 加载
  │
  ▼
生成多个 Asset
  │
  ├── main.js
  ├── vendors.js
  ├── common.js
  ├── runtime.js
  └── xxx.chunk.js

二、为什么要分包?

主要解决两个问题:

  1. 首屏性能:不要让用户打开首页时,把暂时用不到的业务代码和大型第三方库全部下载、解析和执行。
  2. 长期缓存:把变化频率不同的代码拆开。修改业务页面时,React、公共库等未变化的 Chunk 可以继续使用浏览器缓存。
text 复制代码
代码合理拆分
   ↓
首屏代码减少
   ↓
下载 / 解析 / 执行成本降低

稳定的 Chunk 边界
   ↓
contenthash 稳定
   ↓
缓存复用率提高

三、常见策略

1. 多入口

适合多页面、多端等场景:

js 复制代码
entry: {
  admin: "./src/admin.js",
  mobile: "./src/mobile.js",
}

不同入口形成不同的初始 Chunk。

2. 动态 import()

适合 SPA 路由、低频功能、大型第三方库:

js 复制代码
const UserPage = lazy(() => import("./pages/UserPage"));

import() 是异步 Chunk 的边界,Webpack 会把它构建成独立 Chunk,运行到这里时再通过 Webpack Runtime 请求对应资源。

3. SplitChunksPlugin

用于提取公共模块,例如:

text 复制代码
pageA ──┐
        ├── React ──→ vendors.js
pageB ──┘

这样可以避免公共依赖重复打包,并形成独立缓存边界。

4. Runtime Chunk

js 复制代码
optimization: {
  runtimeChunk: "single",
}

把 Webpack 的运行时代码独立出来,主要目的是改善 Chunk 之间的缓存隔离,而不是单纯为了减小文件体积。

四、核心原则

text 复制代码
不是"拆得越多越好"
          ↓
而是找到合理的加载边界
          ↓
首屏代码尽量小
非首屏代码按需加载
公共代码合理复用
变化频率不同的代码尽量隔离
          ↓
同时避免产生大量过小 Chunk

所以真正的代码分割策略应该结合:

首屏加载需求 + 路由边界 + 公共依赖 + 缓存边界 + Chunk 大小 + 网络请求数量

综合设计。

五、一句话总结

代码分割不是简单地"把一个大文件拆成多个小文件",而是通过 Entry、动态 import() 和 SplitChunksPlugin 建立合理的加载边界和缓存边界:首屏只加载必须代码,非首屏按需加载,公共代码复用并长期缓存,同时避免过度拆分。

相关推荐
ttwuai1 小时前
Golang Web后台管理框架推荐:Gin、GoFrame与数据面板项目怎么分
前端·golang·gin
广州华水科技1 小时前
北斗GNSS变形监测系统在水库安全监测中的应用与优势
前端
27669582921 小时前
youdao/有道翻译APP 算法协议分析
开发语言·前端·python·sign·youdao·有道翻译app算法·有道app协议请求
奕鼎竜瑆9 小时前
Solid 前端响应式开发从零到精通
前端·人工智能
动恰客流统计10 小时前
景区客流统计怎么做?兼顾管控与运营的实施方案解析
大数据·前端·人工智能
派小心.11 小时前
A/B测试工具免费版够用吗?
前端·数据分析
前端snow11 小时前
ai agent --- redis 缓存
前端
duanshu_12 小时前
官网表单与下载异常怎么排查?五个环节定位故障
前端·自动化·flyweight
Zhou14113612 小时前
SpringBoot_03_Web开发
前端·spring boot·python