SSR 兼容性
VitePress 是一个静态站点生成器(SSG),它的工作原理是在构建时通过服务器端渲染(SSR)将每个页面渲染成静态 HTML。这意味着你的 Vue 组件代码不仅会在浏览器(客户端)中运行,也会在 Node.js 环境(服务器端)中运行。
因此,你需要确保你的代码是同构的(Isomorphic),即同一份代码能够在这两种环境中正确运行。这通常被称为“SSR 兼容性”。
浏览器/DOM 特有的 API
最常见的 SSR 不兼容问题是直接访问了仅存在于浏览器中的全局变量,如 window 或 document。
错误示例:
javascript
// 在组件的 <script setup> 或 created() 钩子中
// 这会在构建时(Node.js 环境)抛出错误,因为 Node.js 中没有 window 对象
const width = window.innerWidth;正确做法:
将访问浏览器特有 API 的代码移动到只在客户端执行的生命周期钩子中,最常用的是 onMounted。
vue
<script setup>
import { ref, onMounted } from 'vue'
const width = ref(0)
// onMounted 钩子只会在组件被挂载到 DOM 后(即在浏览器中)执行
onMounted(() => {
width.value = window.innerWidth
})
</script>VitePress 提供的辅助工具
VitePress 提供了一些内置的辅助工具来帮助你处理 SSR 兼容性问题。
<ClientOnly /> 组件
如果你有一个组件不兼容 SSR,或者你只想让它在客户端渲染(例如,一个包含大量交互且对 SEO 不重要的组件),你可以使用 <ClientOnly /> 组件来包裹它。
vue
<template>
<div>
<p>这部分内容会被 SSR 渲染。</p>
<ClientOnly>
<!-- 这部分内容以及它的子组件只会在客户端渲染 -->
<MyInteractiveComponent />
</ClientOnly>
</div>
</template>inBrowser 常量
VitePress 提供了一个 inBrowser 常量,你可以用它来有条件地执行只应在浏览器中运行的代码。
vue
<script setup>
import { inBrowser } from 'vitepress'
if (inBrowser) {
// 这里的代码只会在浏览器环境中执行
const geo = navigator.geolocation;
}
</script>第三方库的兼容性
当你使用第三方库时,也要注意它的 SSR 兼容性。一些库可能假设它们只在浏览器环境中运行。
处理技巧:
检查文档:查看库的文档是否提到了 SSR 或 Nuxt/Next.js/VitePress 的用法。
动态导入:如果一个库不兼容 SSR,你可以在
onMounted钩子中动态地import()它,确保它只在客户端被加载和执行。vue<script setup> import { onMounted } from 'vue' onMounted(async () => { const SomeLibrary = (await import('some-non-ssr-library')).default // 现在可以在这里使用 SomeLibrary const instance = new SomeLibrary() }) </script>
确保代码的 SSR 兼容性是使用 VitePress 或任何现代前端框架进行静态站点生成时的关键一步,它可以避免构建错误,并确保你的网站能够被成功地预渲染。