Skip to content

路由处理

在 Vue SSR(Server-Side Rendering)环境中,路由处理和数据预取是两个关键点,它们确保了应用能够根据 URL 正确地渲染页面,并且可以在服务器端获取必要的数据,从而提高首屏加载速度和 SEO 效果。

1. 配置 Vue Router

首先,你需要配置 Vue Router 来管理客户端和服务器端的路由。创建一个 router/index.js 文件来设置路由规则:

javascript
import Vue from "vue";
import Router from "vue-router";
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";

Vue.use(Router);

export function createRouter() {
  return new Router({
    mode: "history",
    routes: [
      { path: "/", component: Home },
      { path: "/about", component: About },
      // 其他路由...
    ],
  });
}

2. Vue main 文件获取路由

js
// ./src/main.js
import Vue from "vue";
import App from "./App.vue";
import createRouter from "./router/index.js";

export default function () {
  const router = createRouter();
  const app = new Vue({
    render: (h) => h(App),
    router, // 确保将 router 挂载到 Vue 实例上
  });
  return { app, router };
}

3. 设置服务器端路由位置

在服务器端入口文件 (entry-server.js) 中,需要设置路由器的位置以匹配当前请求的 URL:

javascript
import { createApp } from "../main";

export default (context) => {
  return new Promise((resolve, reject) => {
    const { app, router, store } = createApp();

    // 设置服务器端路由位置
    router.push(context.url);

    // 等待所有异步组件和钩子完成
    router.onReady(() => {
      const matchedComponents = router.getMatchedComponents();
      if (!matchedComponents.length) {
        return reject({ code: 404 });
      }

      // 继续进行数据预取和其他操作
      resolve(app);
    }, reject);
  });
};

这里我们使用 router.push() 方法将 URL 推送到路由器中,并等待其准备好再继续执行后续逻辑。如果没有任何匹配的组件,我们可以抛出一个 404 错误。

4. 服务端主文件获取路由

js
// ./server/server.js
const express = require("express");
const fs = require("fs");
const { createBundleRenderer } = require("vue-server-renderer");
const serverBundle = require("../dist/vue-ssr-server-bundle.json");
const clientManifest = require("../dist/vue-ssr-client-manifest.json");

const app = express();
app.use(express.static(resolve("../dist")), { index: false });

app.get("*", async (req, res) => {
  // 1. 获取请求router
  const url = req.url;
  try {
    // 2. 创建渲染器
    const renderer = createBundleRenderer(
      serverBundle,
      {
        template: fs.readFileSync("./index.ssr.html", "utf-8"), // 模板文件
      },
      clientManifest
    );
    // 3. 利用渲染器将vue 实例转换成html 字符串,传递url 可以被server 入口函数获取到url
    const html = await renderer.renderToString({ url });
    res.send(html);
  } catch (err) {
    console.error(err);
    if (err.code === 404) {
      res.status(404).send("Page not found");
      return;
    }
    res.status(500).send("Internal Server Error");
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

总结

通过正确配置 Vue Router 和实现数据预取机制,你可以确保你的 Vue SSR 应用程序不仅能够根据 URL 正确地渲染页面,而且可以在服务器端获取必要的数据,从而提升性能和用户体验。

Released under the MIT License.