Skip to content

Commit

Permalink
feat: 实现浏览器端的hydration
Browse files Browse the repository at this point in the history
  • Loading branch information
c0dedance committed Oct 30, 2023
1 parent 1a66b9a commit 076cba0
Showing 1 changed file with 39 additions and 10 deletions.
49 changes: 39 additions & 10 deletions src/runtime/client-entry.tsx
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()

0 comments on commit 076cba0

Please sign in to comment.