Vue路由懒加载(Vue2+Vue3实战详解)| 性能优化必学

0 阅读9分钟

在Vue项目开发中,路由懒加载是前端性能优化的核心手段之一。当项目规模扩大、页面增多时,若一次性加载所有路由组件,会导致首屏加载时间过长、资源浪费,影响用户体验。路由懒加载的核心逻辑的是:按需加载,即只有当用户访问该路由时,才加载对应的组件,从而减小首屏加载体积、提升加载速度。

一、路由懒加载核心原理

Vue3项目默认打包时,所有路由对应的组件会被打包到一个app.js文件中,导致该文件体积过大。浏览器加载页面时,需先下载完整个app.js才能渲染页面,首屏加载延迟明显。

Vue3路由懒加载借助ES6的import()动态导入语法,将不同路由对应的组件分割成独立的代码块(chunk)。打包后,每个路由组件对应一个单独的js文件,只有当用户点击该路由、触发路由跳转时,才会异步请求对应的代码块并加载组件,实现“按需加载”。

补充:import()动态导入语法会返回一个Promise对象,Vue Router会自动处理这个Promise,在组件加载完成后渲染页面,无需手动处理异步逻辑,适配Vue3所有版本。

二、路由懒加载的核心优势

路由懒加载是Vue项目性能优化的“低成本、高收益”手段,核心优势主要有3点:

  • 减小首屏加载体积:无需加载所有路由组件,只加载当前页面(首页)对应的组件,大幅减小首屏js文件体积,提升首屏加载速度。
  • 节省带宽资源:用户未访问的路由组件不会被加载,避免无效资源请求,尤其适合移动端用户(带宽有限场景)。
  • 提升用户体验:首屏加载速度加快,减少用户等待时间,降低页面白屏概率;后续路由跳转时,组件异步加载,不阻塞页面渲染。

三、Vue3路由懒加载完整可复制示例(实战必备)

以下提供完整的Vue3路由懒加载示例,包含3个核心文件(router/index.js、main.js、页面组件),代码可直接复制粘贴到项目中使用,无需修改核心逻辑,仅需调整组件路径即可。

1. 路由配置文件(router/index.js)【核心文件】

完整路由配置,包含懒加载语法、路由守卫(可选)、分包策略,适配Vue3+Vue Router 4.x版本:

// router/index.js(Vue3 完整路由懒加载配置)
import { createRouter, createWebHistory } from 'vue-router'

// 路由懒加载核心:用import()动态导入组件,无需提前引入
// 可直接复制,仅需修改组件路径(../views/xxx.vue)
const Home = () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
const About = () => import(/* webpackChunkName: "About" */ '../views/About.vue')
const User = () => import(/* webpackChunkName: "User" */ '../views/User.vue')
const UserInfo = () => import(/* webpackChunkName: "User" */ '../views/UserInfo.vue')
const NotFound = () => import(/* webpackChunkName: "NotFound" */ '../views/NotFound.vue')

// 完整路由配置(可直接复制使用)
const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: { title: '首页', keepAlive: true } // 可选:路由元信息
  },
  {
    path: '/about',
    name: 'About',
    component: About,
    meta: { title: '关于我们' }
  },
  {
    path: '/user',
    name: 'User',
    component: User,
    children: [
      // 嵌套路由懒加载(同样适用)
      { path: 'info', name: 'UserInfo', component: UserInfo }
    ]
  },
  // 404页面懒加载(必加,提升用户体验)
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: NotFound
  }
]

// Vue3 路由实例创建(固定写法,无需修改)
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // 适配环境变量,避免部署路径问题
  routes
})

// 可选:路由守卫(导航前修改页面标题,可删除)
router.beforeEach((to, from, next) => {
  document.title = to.meta.title || 'Vue3路由懒加载实战'
  next()
})

export default router

2. 入口文件(main.js)【引入路由】

Vue3入口文件,引入路由并挂载到应用,代码可直接复制:

// main.js(Vue3 入口文件,引入路由)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 引入上面配置的路由
import './assets/main.css' // 可选:项目样式文件

// 挂载路由并创建应用(固定写法)
createApp(App)
  .use(router)
  .mount('#app')

3. 页面组件示例(views/Home.vue)【配套示例】

简单的页面组件示例,确保路由懒加载可正常渲染,可直接复制:

<!-- views/Home.vue(首页组件示例) -->
<template>
  <div class="home">
    <h1>Vue3路由懒加载实战</h1>
    <div class="router-link">
      <router-link to="/">首页</router-link>
      <router-link to="/about">关于我们</router-link>
      <router-link to="/user">个人中心</router-link>
      <router-link to="/user/info">用户信息</router-link>
    </div>
    <router-view />
  </div>
</template>

<script setup>
// 可添加自己的业务逻辑,此处仅作示例
console.log('首页组件(懒加载)已加载')
</script>

<style scoped>
.home {
  padding: 20px;
}
.router-link {
  margin-right: 20px;
  text-decoration: none;
  color: #333;
}
.router-link.active {
  color: #42b983;
  font-weight: bold;
}
</style>

4. 其他页面组件(About.vue/User.vue/NotFound.vue)【简化示例】

其他页面组件可参考以下简化模板,复制后修改内容即可:

<!-- views/About.vue(关于我们组件) -->
<template>
  <div class="about">
    <h2>关于我们</h2>
    <p>Vue3路由懒加载完整示例,可直接复制使用</p>
  </div>
</template>

<script setup>
console.log('About组件(懒加载)已加载')
</script>

<!-- views/User.vue(个人中心组件) -->
<template>
  <div class="user">
    <h2>个人中心</h2>
    <router-view />
  </div>
</template>

<script setup>
console.log('User组件(懒加载)已加载')
</script>

<!-- views/NotFound.vue(404组件) -->
<template>
  <div class="not-found">
    <h2>404 Not Found</h2>
    <router-link to="/">返回首页</router-link>
  </div>
</template>

四、Vue3路由懒加载实现方式(补充说明)

上述示例使用的是Vue3官方推荐的懒加载方式(import()动态导入),也是最简洁、最高效的方式,以下补充2种特殊场景的实现方式,按需选择:

方式1:官方推荐(已在示例中使用,优先选择)

// 简洁写法,可指定chunk名称(便于调试)
const Home = () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')

方式2:结合箭头函数与Promise(兼容低版本环境)

若项目需兼容低版本浏览器(不支持ES6 import()语法),可结合Promise手动处理,本质与方式1一致,只是语法更繁琐,目前已很少使用,仅作兼容参考。

// Vue2 路由配置(Vue3可参考,只需修改路由实例创建方式)
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

// 手动封装懒加载函数(兼容低版本环境)
const lazyLoad = (componentPath) => {
  return new Promise((resolve) => {
    // 用require动态导入组件,resolve返回组件
    require(['../views/' + componentPath + '.vue'], (component) => {
      resolve(component.default)
    })
  })
}

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => lazyLoad('Home') // 调用封装的懒加载函数
  },
  {
    path: '/about',
    name: 'About',
    component: () => lazyLoad('About')
  }
]

const router = new VueRouter({
  mode: 'history',
  routes
})

export default router

方式3:Vue2专属(require.ensure 语法)

这是Vue2早期的路由懒加载方式,基于webpack的require.ensure实现,目前已被import()动态导入替代,仅适用于Vue2+webpack3及以下版本,Vue3不支持。

// 仅Vue2 适用(Vue3不支持)
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    // require.ensure(依赖, 回调函数, chunk名称)
    component: resolve => require.ensure([], () => resolve(require('../views/Home.vue')), 'Home')
  },
  {
    path: '/about',
    name: 'About',
    component: resolve => require.ensure([], () => resolve(require('../views/About.vue')), 'About')
  }
]

const router = new VueRouter({
  mode: 'history',
  routes
})

export default router

方式4:带加载状态的懒加载(处理网络异常)

添加加载中、加载失败提示,提升用户体验,可替换示例中的路由组件导入:

// 带加载状态的懒加载组件(可直接替换示例中的导入语句)
const Home = () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
  .then(component => component)
  .catch(() => {
    // 加载失败时,渲染失败提示组件
    return import('../components/LoadFail.vue')
  })

// 加载中提示(可选,需自行创建Loading组件)
const About = () => import(/* webpackChunkName: "About" */ '../views/About.vue')
  .then(component => {
    // 模拟加载延迟(实际无需添加)
    return new Promise(resolve => setTimeout(() => resolve(component), 500))
  })

五、Vue3路由懒加载注意事项

1. 组件路径必须正确

import()中传入的组件路径需是相对路径(以../或./开头),绝对路径会导致打包失败;路径拼写错误会导致组件加载失败,控制台报错“Cannot find module”,需核对views文件夹下的组件名称。

2. 适配Vue Router版本

上述示例适用于Vue Router 4.x(Vue3专属版本),若使用低版本Vue Router,需升级版本(npm install vue-router@4),否则会出现语法错误。

3. 避免过度懒加载

首页、高频访问页面(如首页、个人中心)建议不懒加载,直接打包到首屏js中,避免用户首次访问时出现加载延迟;低频访问页面(如设置、帮助中心)适合懒加载。

4. Vue3与Vue2的路由实例创建差异

Vue3中,路由实例创建方式由new VueRouter()改为createRouter(),且需引入对应的history模式(createWebHistory / createWebHashHistory),懒加载组件的语法与Vue2完全一致,只需注意路由实例的创建差异。

5. 分包策略优化

对于大型项目,可将多个相关路由组件打包到同一个chunk中(如示例中User和UserInfo共用“User”chunk),减少请求次数,提升跳转速度,无需额外配置,只需保证webpackChunkName相同即可。

6. 部署路径注意事项

示例中使用createWebHistory(import.meta.env.BASE_URL),适配不同部署环境(开发、测试、生产),无需手动修改;若直接写死路径(如createWebHistory('/')),部署到子路径时会出现路由跳转异常。

六、进阶优化:路由懒加载结合分包策略

对于大型项目,可结合webpack分包策略,将多个相关路由组件打包到同一个chunk中,减少请求次数。例如,将“用户相关”的路由(User、UserInfo、UserSetting)打包到同一个chunk:

// 同一模块的路由组件,打包到同一个chunk(webpackChunkName相同)
const User = () => import(/* webpackChunkName: "user" */ '../views/User.vue')
const UserInfo = () => import(/* webpackChunkName: "user" */ '../views/UserInfo.vue')
const UserSetting = () => import(/* webpackChunkName: "user" */ '../views/UserSetting.vue')

const routes = [
  { path: '/user', component: User },
  { path: '/user/info', component: UserInfo },
  { path: '/user/setting', component: UserSetting }
]

说明:相同webpackChunkName的组件,打包时会合并到同一个chunk文件(如user.[hash].js),用户访问其中一个路由时,会加载整个chunk,后续访问该模块的其他路由时,无需再次请求,提升跳转速度。

七、进阶优化:路由懒加载结合Pinia

大型项目中,可结合Pinia管理全局状态,在路由懒加载时判断用户权限,示例如下(可直接复制添加到router/index.js):

// 结合Pinia权限判断的路由懒加载(可选)
import { useUserStore } from '@/store/user'

// 权限路由懒加载(需登录才能访问)
const UserSetting = () => {
  const userStore = useUserStore()
  // 判断用户是否登录,未登录跳转到首页
  if (!userStore.token) {
    router.push('/')
    return import('../views/Login.vue')
  }
  return import(/* webpackChunkName: "User" */ '../views/UserSetting.vue')
}

// 路由配置中添加
{
  path: '/user/setting',
  name: 'UserSetting',
  component: UserSetting,
  meta: { requireAuth: true } // 标记需要权限
}

八、总结

上述提供的Vue3路由懒加载代码可直接复制粘贴到项目中使用,核心是借助import()动态导入语法实现按需加载,优化首屏性能。

实战建议:

  • 直接复制router/index.js、main.js和页面组件示例,仅修改组件路径即可快速集成;
  • 根据项目需求,添加路由守卫、权限判断、加载状态提示;
  • 大型项目结合分包策略,合并相关路由组件,减少请求次数;
  • 部署时注意使用import.meta.env.BASE_URL,避免路由跳转异常。

掌握Vue3路由懒加载,是前端性能优化的必备技能,上述完整示例可覆盖大部分项目场景,新手可直接上手,无需额外调试。