Vueで使う
@tuvix.js/vueはVue 3のルートコンポーネントをマイクロアプリに変換し、サーバーレンダリングされたマークアップをハイドレートし、サーバーでコンポーネントをHTMLにレンダリングします。
インストール
pnpm add @tuvix.js/vue vue
# for renderVueToString on the server
pnpm add @vue/server-rendererコンポーネントをマイクロアプリにする
// src/main.ts
import { createVueMicroApp } from '@tuvix.js/vue';
import { createPinia } from 'pinia';
import { analytics } from './analytics-plugin';
import App from './App.vue';
export default createVueMicroApp({
name: 'settings',
App,
plugins: [createPinia(), [analytics, { id: 'G-123' }]],
});| オプション | 型 | 説明 |
|---|---|---|
name | string | 必須。登録したアプリ名と一致する必要があります。 |
App | Component | 必須。ルートコンポーネント。 |
plugins | Array<Plugin | [Plugin, ...options]> | マウントのたびにapp.use(plugin, ...options)でインストールされます。 |
bootstrap | () => void | Promise<void> | 最初のマウントの前に1回実行されます。 |
ssr | boolean | サーバーのマークアップをハイドレートします。createSsrVueMicroAppはこれを設定します。 |
コンテナごとに専用のVueアプリが作成されるため、マウントのたびに各プラグインのinstallが再度実行されます。createPinia()のようなプラグインのインスタンスは、そのモジュールのすべてのマウントで共有されます。マウントごとに専用のストアが必要な場合は、プラグイン関数の中でインスタンスを作成します。
すでにこのアプリを持つコンテナにマウントすると、まず古いインスタンスをアンマウントします。unmountはアプリを破棄し、コンテナを空にしてtuvix:unmountedをディスパッチします。
プロパティ
アダプターはプロパティをルートコンポーネントに渡し、さらに任意の子孫コンポーネント向けに'tuvixProps'(TUVIX_PROPS_KEY)としてprovideします。
<!-- App.vue -->
<script setup lang="ts">
import { inject } from 'vue';
import { TUVIX_PROPS_KEY } from '@tuvix.js/vue';
defineProps<{ userId: string; theme?: 'light' | 'dark' }>();
const all = inject<Record<string, unknown>>(TUVIX_PROPS_KEY);
</script>
<template>
<div :class="theme">User {{ userId }} ({{ Object.keys(all ?? {}).length }} props)</div>
</template>update({ props })はshallowReactiveオブジェクト内のプロパティを置き換え、Vueの次のtickを待ちます。ルートコンポーネントは新しい値で再レンダリングされ、ローカルの状態は維持されます。新しいプロパティにないキーは削除されます。containerを指定しない場合、updateはモジュールのすべてのマウントを更新します。
import { createOrchestrator } from '@tuvix.js/core';
const orchestrator = createOrchestrator();
await orchestrator.updateAppProps('settings', { theme: 'dark' });サーバーレンダリングとハイドレーション
サーバーではrenderVueToStringでレンダリングし、クライアントではcreateSsrVueMicroAppでハイドレートします。
// server-only module
import { renderVueToString } from '@tuvix.js/vue/server';
import Newsletter from './Newsletter.vue';
export async function renderNewsletter(list: string): Promise<string> {
const ssrContext: { teleports?: Record<string, string> } = {};
const html = await renderVueToString(Newsletter, { list }, [], ssrContext);
return html; // ssrContext.teleports holds <Teleport> output
}// client
import { createSsrVueMicroApp } from '@tuvix.js/vue';
import Newsletter from './Newsletter.vue';
export const newsletter = createSsrVueMicroApp({ name: 'newsletter', App: Newsletter });renderVueToString(App, props?, plugins?, ssrContext?)は、クライアントと同じルートでAppをラップします。そのため、サーバーでもinject('tuvixProps')が動作し、ハイドレーションが一致します。- サーバーのコード(サーバー関数、APIルート、またはサーバーエントリー)からのみ呼び出します。ブラウザーでは
''を返します。アイソモーフィックなルートローダーはブラウザーでも実行されるため、その場合バンドラーはVueのサーバーレンダラーをクライアントに配布してしまいます。 ssr: trueでコンテナにサーバーのマークアップがある場合、アダプターはcreateSSRAppを呼び出し、サーバーのDOMノードを維持します。空のコンテナはcreateAppで新規にレンダリングされます。- HTMLにはCSSが含まれません。ViteはSFCの
<style>ブロックをJavaScriptから注入し、それはハイドレーションの開始後になります。@tuvix.js/viteで<head>にスタイルシートをリンクします。SSRアイランドを参照してください。
Reactホスト内では、TuvixIslandでモジュールをマウントします。
コンポーザブル
useTuvixBus
<script setup lang="ts">
import { ref } from 'vue';
import { getGlobalBus } from '@tuvix.js/event-bus';
import { useTuvixBus } from '@tuvix.js/vue';
const count = ref(0);
useTuvixBus<{ itemCount: number }>(getGlobalBus(), 'cart:updated', ({ itemCount }) => {
count.value = itemCount;
});
</script>
<template>
<span class="badge">{{ count }}</span>
</template>onMountedで購読し、onUnmountedで購読を解除し、早期にクリーンアップするための関数を返します。
useTuvixProps
useTuvixProps(initialProps, bus?, updateEvent = 'tuvix:props:update')は、updateEventで発行された各ペイロードをマージするShallowRefを返します。Tuvix.jsにこのイベントを発行する処理はありません。アダプターを使う場合、updateAppPropsで渡したプロパティはすでにコンポーネントを再レンダリングするため、これが必要になることはほとんどありません。
エッジケース
~/utilsのようなパスエイリアスは、.vueファイル内でも解決できる必要があります。エイリアスがvite-tsconfig-pathsから来ている場合は、そのtsconfigのincludeに**/*.vueを含めるか、Viteの設定でresolve.aliasを設定します。トラブルシューティングを参照してください。- マウント中のsetup、render、ライフサイクルフックのエラーは、本番ビルドでも
mountをrejectし、tuvix:errorをディスパッチします。プラグイン自身のapp.config.errorHandlerも引き続き実行されます。 - このモジュールがマウントしたことのないコンテナに対する
unmountは何もしません。
API
| エクスポート | 用途 |
|---|---|
createVueMicroApp({ name, App, plugins?, bootstrap?, ssr? }) | Vueマイクロアプリのモジュール |
createSsrVueMicroApp({ name, App, plugins?, bootstrap? }) | ssr: trueを設定した同等のもの |
TUVIX_PROPS_KEY | リアクティブなプロパティのインジェクションキー('tuvixProps') |
useTuvixBus(bus, event, handler) | コンポーネントに紐づいたイベントバスの購読 |
useTuvixProps(initial, bus?, event?) | バスのイベントからマージされるShallowRef |
@tuvix.js/vue/serverのrenderVueToString(App, props?, plugins?, ssrContext?) | サーバーHTML |