项目概况

SSR

2026-01-291 min read未分类
vitepress

SSR

SSR: Server-Side Render 服务端渲染的意思

在使用 VitePress 进行服务端打包的时候, 因为是 Node的打包环境,所以并没有 document 对象,经常会打包失败。比如下面。

text
1✓ building client + server bundles... 2build error: 3ReferenceError: document is not defined // [!code focus] 4 at file:///Users/liuxin/WebstormProjects/lxchinesszz/docs/node_modules/.pnpm/vue-echarts@7.0.3_echarts@5.5.1_vue@3.5.9/node_modules/vue-echarts/dist/index.js:145:1 5 at ModuleJob.run (node:internal/modules/esm/module_job:262:25) 6 at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:485:26) 7 at async build (file:///Users/liuxin/WebstormProjects/lxchinesszz/docs/node_modules/.pnpm/vitepress@1.0.1_@algolia+client-search@5.6.1_@types+node@22.5.4_search-insights@2.17.2/node_modules/vitepress/dist/node/serve-C_2bYS0g.js:46722:24) 8

解决办法

=defineClientComponent=

VitePress

VitePress 为导入 Vue 组件提供了一个方便的辅助函数,该组件可以在导入时访问浏览器 API。目标组件将仅在 wrapper 组件的 mounted 钩子中导入。

js
1<script setup> 2import { defineClientComponent } from 'vitepress' 3 4const ClientComp = defineClientComponent(() => { 5 return import('component-that-access-window-on-import') 6}) 7</script> 8 9<template> 10 <ClientComp /> 11</template>

参数传递

传参的语法和 h函数一样。

  • function h(type: string | Component,props?: object | null, children?: Children | Slot | Slots): VNode
text
1const ClientComp = defineClientComponent( 2 () => import('component-that-access-window-on-import'), 3 4 // 参数传递给 h() - https://cn.vuejs.org/api/render-function.html#h 5 [ 6 { 7 ref: clientCompRef 8 }, 9 { 10 default: () => 'default slot', 11 foo: () => h('div', 'foo'), 12 bar: () => [h('span', 'one'), h('span', 'two')] 13 } 14 ], 15 16 // 组件加载后的回调,可以是异步的 17 () => { 18 console.log(clientCompRef.value) 19 }

条件导入

除此之外,还可以使用条件导入

js
1export function useComponents(app) { 2 app.mixin({ 3 async mounted() { 4 import('v-ui').then((m) => { 5 app.use(m.default); 6 }); 7 }, 8 }); 9} 10 11export default { 12 ...DefaultTheme, 13 Layout, 14 enhanceApp(ctx: EnhanceAppContext) { 15 DefaultTheme.enhanceApp(ctx); 16 useComponents(ctx.app); 17 }, 18};