統一的なコンポーネント定義からSSRとHydrationを行うフレームワーク
サーバーで renderToString(Counter, { count: 10 }) を実行した想定
サーバーで初期アイテム付きでレンダリング
SSRなしでJavaScriptのみでレンダリング
// 1. コンポーネント定義 (共通)
const Counter = defineComponent({
name: 'my-counter',
styles: `...`,
initialState: { count: 0 },
render(state) {
return `<div>Count: ${state.count}</div>...`;
},
handlers: {
increment: (state) => ({ count: state.count + 1 }),
},
});
// 2. サーバーサイド (Node.js)
const html = renderToString(Counter, { count: 10 });
// 3. クライアントサイド (Browser)
registerComponent(Counter); // Hydration
┌─────────────────────────────────────────────────────┐
│ Server │
│ │
│ Component Def ──► renderToString() ──► HTML │
│ │ │ │
│ │ ┌──────────────────────┐│ │
│ │ │ <my-counter> ││ │
│ │ │ <template>... ││ │
│ │ │ data-state="..." ││ │
│ │ │ </my-counter> ││ │
│ │ └──────────────────────┘│ │
└───────┼────────────────────────────────────┼────────┘
│ │
│ HTTP Response │
│ ▼
┌───────┼────────────────────────────────────┬────────┐
│ Browser │ │
│ │ │ │
│ │ HTML Parse ──► Declarative Shadow DOM │
│ │ (即座に表示) │
│ │ │ │
│ ▼ │ │
│ registerComponent() ──► customElements.define() │
│ │ │
│ │ connectedCallback() │
│ │ ├── shadowRoot exists? ──► Hydrate │
│ │ │ └── attachEventListeners() │
│ │ └── no shadowRoot ──► CSR Render │
│ │ │
│ ▼ │
│ Interactive Component │
└─────────────────────────────────────────────────────┘
JavaScript読み込み前...