--- outline: deep --- # SSR 互換性 {#ssr-compatibility} VitePress は本番ビルド時に、Node.js 上で Vue のサーバーサイドレンダリング(SSR)機能を使ってアプリを事前レンダリングします。つまり、テーマコンポーネント内のすべてのカスタムコードは SSR 互換性の対象になります。 [公式 Vue ドキュメントの SSR セクション](https://vuejs.org/guide/scaling-up/ssr.html)では、SSR とは何か、SSR と SSG の関係、そして SSR に優しいコードを書く際の一般的な注意点が解説されています。経験則としては、**ブラウザ / DOM API へのアクセスは Vue コンポーネントの `beforeMount` または `mounted` フック内に限定** するのが安全です。 ## `` {#clientonly} SSR に適さないコンポーネント(例:カスタムディレクティブを含むなど)を使用・デモする場合は、組み込みの `` コンポーネントでラップできます。 ```md ``` ## インポート時に Browser API にアクセスするライブラリ {#libraries-that-access-browser-api-on-import} 一部のコンポーネントやライブラリは **インポート時に** ブラウザ API にアクセスします。インポート時にブラウザ環境を前提とするコードを使うには、動的インポートが必要です。 ### mounted フック内でのインポート {#importing-in-mounted-hook} ```vue ``` ### 条件付きインポート {#conditional-import} [`import.meta.env.SSR`](https://vitejs.dev/guide/env-and-mode.html#env-variables) フラグ(Vite の環境変数の一部)を使って、依存関係を条件付きでインポートすることもできます。 ```js if (!import.meta.env.SSR) { import('./lib-that-access-window-on-import').then((module) => { // ここでコードを利用 }) } ``` [`Theme.enhanceApp`](./custom-theme#theme-interface) は非同期にできるため、**インポート時に Browser API に触れる Vue プラグイン** を条件付きでインポート・登録できます。 ```js [.vitepress/theme/index.js] /** @type {import('vitepress').Theme} */ export default { // ... async enhanceApp({ app }) { if (!import.meta.env.SSR) { const plugin = await import('plugin-that-access-window-on-import') app.use(plugin.default) } } } ``` TypeScript を使う場合: ```ts [.vitepress/theme/index.ts] import type { Theme } from 'vitepress' export default { // ... async enhanceApp({ app }) { if (!import.meta.env.SSR) { const plugin = await import('plugin-that-access-window-on-import') app.use(plugin.default) } } } satisfies Theme ``` ### `defineClientComponent` VitePress は、**インポート時に Browser API にアクセスする Vue コンポーネント** を読み込むためのユーティリティを提供します。 ```vue ``` ターゲットコンポーネントに props / children / slots を渡すこともできます。 ```vue ``` ターゲットコンポーネントは、ラッパーコンポーネントの mounted フックで初めてインポートされます。