代码分割(Code Splitting)的核心目标是:把一个大的 JS Bundle 拆成多个小文件,按需加载,从而减少首屏加载时间。
因为你在用 Vue3 + Vite(我记得你之前说过),所以我重点讲 Vite / Vue3 项目里的代码分割,同时顺带讲一下原理。
一、最简单的代码分割方式:import()
最常见的方法就是 动态导入(Dynamic Import) 。
示例
// 普通导入(不会代码分割)
import User from './User.js'
打包后会合并进主 bundle。
改成动态导入
import('./User.js').then(module => {
const User = module.default
})
打包后:
main.js
User.xxx.js
只有执行到 import() 才会加载 User.xxx.js。
二、Vue Router 自动代码分割(最常用)
Vue 项目最常见的代码分割就是 路由级别拆分。
不拆分写法
import Home from '@/views/Home.vue'
const routes = [
{
path: '/',
component: Home
}
]
代码分割写法
const routes = [
{
path: '/',
component: () => import('@/views/Home.vue')
}
]
打包结果:
index.js
Home.xxx.js
About.xxx.js
访问 /home 时才会下载 Home.xxx.js。
这叫:
Route Level Code Splitting(路由级代码分割)
三、Vue 组件懒加载
如果某个组件很大,也可以单独拆。
示例
<script setup>
import { defineAsyncComponent } from 'vue'
const BigComponent = defineAsyncComponent(() =>
import('./BigComponent.vue')
)
</script>
<template>
<BigComponent />
</template>
当组件渲染时才会加载。
四、Vite 手动拆包(高级)
有时候需要 把第三方库单独打包。
例如:
- vue
- lodash
- echarts
可以配置:
vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vue: ['vue', 'vue-router'],
lodash: ['lodash'],
echarts: ['echarts']
}
}
}
}
})
打包后:
index.js
vue.xxx.js
lodash.xxx.js
echarts.xxx.js
好处:
- 浏览器缓存更稳定
- 更新业务代码不会影响库缓存
五、常见拆包策略(面试高频)
一般拆成:
1 业务代码
index.js
2 vendor 包
vendor.js
包含:
vue
vue-router
axios
3 大型库
echarts.js
lodash.js
4 路由页面
home.js
user.js
admin.js
六、打包结果示例
原本:
bundle.js (2MB)
拆分后:
index.js (120kb)
vendor.js (300kb)
home.js (50kb)
user.js (80kb)
echarts.js (500kb)
访问首页:
index.js
vendor.js
home.js
进入图表页面:
echarts.js
七、代码分割原理(面试加分)
Webpack / Vite 的代码分割依赖 ES Module 的动态 import:
import('./module.js')
构建工具会:
1️⃣ 识别 import()
2️⃣ 把模块拆成独立 chunk
3️⃣ 运行时通过 <script> 动态加载
浏览器下载:
/assets/module-abc123.js
八、再进阶一点(真正的性能优化)
实际项目会组合:
1 路由懒加载
component: () => import('@/views/Home.vue')
2 第三方库拆包
manualChunks
3 组件级懒加载
defineAsyncComponent
4 预加载
<link rel="prefetch">
<link rel="preload">
九、前端面试标准答案总结
如果面试问:
如何实现代码分割?
回答结构:
1️⃣ 使用 ES dynamic import
import()
2️⃣ 路由懒加载
component: () => import()
3️⃣ 组件懒加载
defineAsyncComponent
4️⃣ 构建工具拆包
manualChunks
splitChunks
5️⃣ 目的
- 减少首屏加载
- 提高缓存利用
- 按需加载资源
如果你愿意,我可以再给你一份 前端面试最爱问的 Code Splitting 终极答案(含 Webpack + Vite + 浏览器原理) ,很多人其实答不全,我可以帮你整理一套 面试吊打面试官版本 😄