Skip to content

项目中VueRouter采用组件懒加载的好处是啥?

  • 实现按需加载,只有当用户到特定路由才会去加载相应组件代码。

  • 路由组件不使用懒加载,项目打包时将会把所有页面打包成一个文件(app.js),首页一次性加载全部资源,导致页加载时会一次性请求并解析这个包含所有页面的大包,加载速度慢,用户体验差。

    1. 白屏时间延长(尤其在弱网环境下)
    2. 首屏内容加载时间(FCP)增加
    3. 最大内容绘制时间(LCP)增加
  • 路由组件使用懒加载,项目打包后会生成多个 chunk 文件,不仅页面的js会被拆分,css同样也会被拆分。

延伸:为什么组件懒加载后打包会被拆分?

组件懒加载(动态导入)之所以能实现打包文件拆分,本质上是因为现代构建工具对 ES 模块动态导入语法(import())的特殊处理。

动态导入语法被识别为分割点,构建工具会将动态导入的模块及其依赖单独打包

下面分别从 Webpack 和 Vite 的实现机制来解释:

Webpack的实现原理

1. 核心机制:Code Splitting

Webpack通过Code Splitting实现代码分割,当遇到动态导入语法时,会将被导入的模块单独打包成一个Chunk文件。

关键配置

javascript
// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all', // 所有类型的chunk都进行分割
      minSize: 20000, // 最小分割大小
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors'
        }
      }
    }
  }
}

2. 动态导入处理流程

javascript
// 静态导入(会打包到同一个文件)
import Home from './pages/Home.vue';

// 动态导入(懒加载)
const Home = () => import('./pages/Home.vue');

当Webpack遇到import('./pages/Home.vue')时:

  1. 分析Home.vue及其依赖的模块
  2. 将这些模块单独打包到一个新的Chunk文件(如1.js
  3. 在运行时,当需要渲染Home组件时,才会通过JSONP异步加载这个Chunk文件

3. 打包结果示例

假设项目结构:

src/
  pages/
    Home.vue
    User.vue
    Product.vue
  App.vue

打包后文件结构

dist/
  assets/
    main.js        // 主应用代码
    1.js           // Home组件及其依赖
    2.js           // User组件及其依赖
    3.js           // Product组件及其依赖

Vite的实现原理

1. 基于ESModule的原生实现

Vite利用浏览器原生支持的ES模块系统(<script type="module">),在开发阶段直接使用浏览器加载模块,无需打包。

关键特性

  • 预构建:启动时将依赖(如Vue、axios)预构建为单个模块
  • 按需加载:开发阶段通过浏览器原生动态导入加载组件

2. 生产环境打包机制

Vite在生产环境使用Rollup打包,但保留了动态导入的语义:

javascript
// Vite中的懒加载写法
const Home = () => import('./pages/Home.vue');

Vite/Rollup会:

  1. 分析模块依赖关系
  2. 将动态导入的组件及其依赖单独打包成一个Chunk
  3. 使用ESM格式输出,通过浏览器原生支持的动态导入加载

3. 打包结果示例

javascript
// 打包后的main.js(简化)
const loadHome = () => import('./home-5f3a2.js');

// 打包后的home-5f3a2.js
const Home = {
  // Home组件的实现
}
export default Home;

两者对比

特性WebpackVite
实现基础自定义模块加载系统浏览器原生ESModule
打包方式所有模块统一打包(需要配置splitChunks)按需打包,保留ESModule结构
动态导入处理转换为JSONP异步加载保留原生import()语法
生产环境Chunk命名可通过magic comment自定义基于模块路径自动生成哈希文件名
性能大型项目打包慢,运行时按需加载开发阶段无需打包,生产环境打包快

懒加载的性能优化效果

不使用懒加载

main.js (1.2MB)

首页加载时需要下载并解析1.2MB的JS文件

使用懒加载

main.js (300KB)  // 核心应用代码
home.js (200KB)  // Home页面
user.js (250KB)  // User页面
product.js (400KB) // Product页面

首页只需加载300KB的核心代码,其他页面按需加载,显著提升首屏加载速度