预渲染后首页SEO正常,但其他路由页面还是空白,怎么回事?

梦轩 Dev 阅读 6

我用的是 Vue 3 + Vite 项目,为了 SEO 接入了 prerender-spa-plugin 做预渲染。本地 build 之后,首页 index.html 确实有完整内容,Google 模拟抓取也正常。但像 /about/product/123 这些动态路由,生成的 HTML 文件打开还是只有根节点,内容是空的。

我查了插件配置,routes 里明明加了这些路径,也确认输出目录里有对应的 about/index.html 文件。但里面的 body 还是只有

,没看到实际 DOM。是不是因为这些页面依赖异步数据?但我已经在组件里用了 onMounted 加载,难道预渲染不等异步完成?

这是我的插件配置:

new PrerenderSPAPlugin({
  staticDir: path.join(__dirname, 'dist'),
  routes: ['/', '/about', '/product/123'],
  renderer: new Renderer({
    inject: {
      foo: 'bar'
    },
    headless: true,
    renderAfterDocumentEvent: 'custom-render-trigger'
  })
})

我在 main.js 里 emit 了这个事件,但好像没生效。到底该怎么让预渲染等数据加载完再生成 HTML?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
东方铭轩
这确实是 prerender-spa-plugin 常见的问题,主要是预渲染时没处理好异步数据。我遇到过好几次,分享下解决方案。

首先确认你的异步数据是不是真的加载完了。onMounted 在预渲染环境是不工作的,你得用服务端渲染兼容的方式。两种常见解决方案:

1. 用 renderAfterTime 硬等(不推荐但简单):
renderer: new Renderer({
renderAfterTime: 5000 // 等5秒
})


2. 推荐用事件触发,但要注意事件要在数据加载完成后触发。比如在获取数据的 Promise 后:
fetchData().then(() => {
document.dispatchEvent(new Event('custom-render-trigger'))
})


另外检查下你的路由配置,如果是动态路由(比如 /product/:id),需要确保预渲染时有真实数据。可以在插件配置里写死几个测试用的路由:
routes: ['/', '/about', '/product/1', '/product/2']


还有个小坑,vue3 可能会因为 hydration 问题导致内容消失,可以在 app 挂载时加个判断:
if (window.__PRERENDER_INJECTED) {
app.mount('#app', true)
} else {
app.mount('#app')
}


最后记得在本地起个静态服务器测试,直接打开文件会因为 file://协议出问题。可以用 serve 或者 http-server:
npx serve dist
点赞
2026-03-05 04:05