Vite 3 + Vue 3 异步加载路由后挂载 APP 实例:解决生产环境页面空白问题
在使用 Vite 3 和 Vue 3 开发应用时,异步加载路由是一个常见的做法,但在某些情况下,这种方式可能会导致生产环境下页面出现空白。
问题描述
在我的项目中,我在 main.ts
中使用了顶层 await
来等待路由初始化。这一部分代码如下:
// main.ts
console.log("execute 111");
// 路由初始化完成后挂载 APP 实例
await router.isReady();
console.log("execute 222");
app.mount("#app");
在开发环境中,这段代码运行正常,控制台打印出 execute 111
和 execute 222
,页面也能正确访问。然而,在生产环境中,只有 execute 111
被打印,页面却是一片空白,并且控制台没有报错信息。
原因分析
经过排查,我发现问题出现在路由配置上。首页路由使用了异步懒加载:
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
const constantRoutes: RouteRecordRaw[] = [
{
path: "/",
name: "home",
component: () => import("@/views/home/index.vue"),
},
{
path: "/:pathMatch(.*)",
name: "404",
component: () => import("@/views/error/404.vue"),
},
];
由于 await router.isReady()
是一个顶层 await
,它会阻塞资源的获取。这使得首页组件无法正确加载,从而造成了死循环:路由在等待访问者的同时,访问者又在等待路由的加载。
解决方案
方法一:直接加载首页组件
为了避免这种情况,我将首页路由的配置修改为直接加载组件,而其他页面仍然使用懒加载:
// router/index.ts
import Home from "@/views/home/index.vue";
const constantRoutes: RouteRecordRaw[] = [
{
path: "/",
name: "home",
component: Home, // 直接加载
},
{
path: "/:pathMatch(.*)",
name: "404",
component: () => import("@/views/error/404.vue"),
},
];
通过这种方式,首页路由会立即初始化,从而避免了页面空白的问题。
方法二:使用 .then()
处理异步加载
如果希望保持路由配置中的懒加载状态,可以使用 .then()
来处理路由初始化,而不是顶层 await
。修改 main.ts
如下:
// main.ts
router
.isReady()
.then(() => {
app.mount("#app");
})
.catch((err) => {
console.error(err);
});
这种方法不会阻塞资源的加载,并且在生产环境中能够正常显示页面。