You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在基于Vite构建的Vue SSR项目中正确集成Vue Router?

问题原因

  • 当前entry-server.js、entry-client.js中未完成路由注册、服务端路径匹配逻辑,仅创建了根App实例,仅能渲染App.vue的默认内容
  • 服务端收到请求后未把当前访问路径传递给服务端路由做匹配,路由无法识别需要渲染的对应组件
  • 根组件App.vue中未添加<router-view>占位符,路由匹配到的组件没有渲染出口

注意:SSR场景下路由、全局状态管理类实例必须每次请求创建新实例,不可复用单例,避免多请求之间数据污染。

修复步骤

1. 路由配置调整(/src/router/index.js)

import { createRouter, createMemoryHistory, createWebHistory } from 'vue-router'
// 导入自定义路由组件
import Home from './views/Home.vue'
import About from './views/About.vue'

// 导出路由创建函数,每次调用生成全新路由实例
export function createMyRouter() {
  return createRouter({
    // 服务端使用内存历史模式,客户端使用浏览器历史模式
    history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
    routes: [
      { path: '/', component: Home },
      { path: '/about', component: About }
      // 其余路由按实际需求补充
    ]
  })
}

2. entry-server.js 修改

import { createApp } from "vue";
import { renderToString } from "@vue/server-renderer";
import App from "./App.vue";
import { createMyRouter } from './router'

// 新增接收请求路径参数
export async function render(url) {
 const app = createApp(App);
 const router = createMyRouter()
 app.use(router)
 
 // 路由跳转到当前请求路径,等待路由加载完成后再渲染
 await router.push(url)
 await router.isReady()
 
 const appContent = await renderToString(app);
 return appContent;
}

3. entry-client.js 修改

import { createApp } from "vue";
import App from "./App.vue";
import { createMyRouter } from './router'

const app = createApp(App);
const router = createMyRouter()
app.use(router)

// 等待客户端路由就绪后再挂载,避免hydration不匹配问题
router.isReady().then(() => {
  app.mount("#app");
})

4. main.js 修改

const { createServer } = require("vite");
const server = require("express")();
const fs = require("fs");
const path = require("path");

async function main() {
 const vite = await createServer({ server: { middlewareMode: true } });
 server.use(vite.middlewares);
 server.get("*", async (req, res) => {
let html = fs.readFileSync(path.resolve(__dirname, "index.html"), "utf-8");
const { render } = await vite.ssrLoadModule("/src/entry-server.js");
// 把当前请求的路径传递给服务端渲染方法
const appContent = await render(req.url);
html = html.replace("<!--ssr-->", appContent);
res.end(html);
});
server.listen(8080);
}

main();

5. App.vue 新增路由占位符

在App.vue模板的对应渲染位置添加路由出口:

<template>
  <!-- 原有App.vue的公共布局内容 -->
  <router-view></router-view>
</template>

内容的提问来源于stack exchange,提问作者Sergio AC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 15:15:02