项目中VueRouter采用组件懒加载的好处是啥?
实现
按需加载,只有当用户到特定路由才会去加载相应组件代码。路由组件不使用懒加载,项目打包时将会把所有页面打包成一个文件(app.js),首页一次性加载全部资源,导致页加载时会一次性请求并解析这个包含所有页面的大包,加载速度慢,用户体验差。
- 白屏时间延长(尤其在弱网环境下)
- 首屏内容加载时间(FCP)增加
- 最大内容绘制时间(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')时:
- 分析
Home.vue及其依赖的模块 - 将这些模块单独打包到一个新的Chunk文件(如
1.js) - 在运行时,当需要渲染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会:
- 分析模块依赖关系
- 将动态导入的组件及其依赖单独打包成一个Chunk
- 使用ESM格式输出,通过浏览器原生支持的动态导入加载
3. 打包结果示例
javascript
// 打包后的main.js(简化)
const loadHome = () => import('./home-5f3a2.js');
// 打包后的home-5f3a2.js
const Home = {
// Home组件的实现
}
export default Home;两者对比
| 特性 | Webpack | Vite |
|---|---|---|
| 实现基础 | 自定义模块加载系统 | 浏览器原生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的核心代码,其他页面按需加载,显著提升首屏加载速度