diff --git a/src/runtime/client-entry.tsx b/src/runtime/client-entry.tsx index 4dfa258..fae777f 100644 --- a/src/runtime/client-entry.tsx +++ b/src/runtime/client-entry.tsx @@ -1,23 +1,52 @@ -import { createRoot } from 'react-dom/client' +import { createRoot, hydrateRoot } from 'react-dom/client' import { BrowserRouter } from 'react-router-dom' import App, { initPageData } from './App' import { DataContext } from './hooks' +import type { ComponentType } from 'react' + +declare global { + interface Window { + ISLANDS: Record> + ISLAND_PROPS: unknown[] + } +} async function renderInBrowser() { const containerEl = document.getElementById('root') if (!containerEl) { throw new Error('#root element not found') } - // 初始化 PageData - const pageData = await initPageData(location.pathname) + // dev 下走全量的 Hydration + if (import.meta.env.DEV) { + // 初始化 PageData + const pageData = await initPageData(location.pathname) - createRoot(containerEl).render( - - - - - - ) + createRoot(containerEl).render( + + + + + + ) + } else { + // 生产环境下的 Partial Hydration + const islands = document.querySelectorAll('[__island]') // 在自定义jsx中给islands组件包裹`div[__island]` + if (!islands.length) { + return + } + /* + window.ISLANDS = { + Aside: Aside + } + */ + for (const island of islands) { + // Aside:0 + const [id, index] = island.getAttribute('__island').split(':') + const Element = window.ISLANDS[id] as ComponentType + // 单独对每个 island 组件 Hydrate,多次 hydrateRoot 不会像 createRoot 会产生多个 React ·实例 + hydrateRoot(island, ) + } + } } renderInBrowser()