-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
39 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string, ComponentType<unknown>> | ||
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( | ||
<DataContext.Provider value={pageData}> | ||
<BrowserRouter> | ||
<App /> | ||
</BrowserRouter> | ||
</DataContext.Provider> | ||
) | ||
createRoot(containerEl).render( | ||
<DataContext.Provider value={pageData}> | ||
<BrowserRouter> | ||
<App /> | ||
</BrowserRouter> | ||
</DataContext.Provider> | ||
) | ||
} 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<unknown> | ||
// 单独对每个 island 组件 Hydrate,多次 hydrateRoot 不会像 createRoot 会产生多个 React ·实例 | ||
hydrateRoot(island, <Element {...window.ISLAND_PROPS[index]} />) | ||
} | ||
} | ||
} | ||
|
||
renderInBrowser() |