ssr)
vue31. 項目結(jié)構(gòu)src/ ├── entry-server.js # 服務(wù)端入口 ├── entry-client.js # 客戶端入口水合 ├── App.vue server.js # Node服務(wù) index.html # HTML模板2. 關(guān)鍵代碼server.jsNode 服務(wù)import express from express import { createSSRApp } from vue import { renderToString } from vue/server-renderer import App from ./App.vue const app express() app.get(*, async (req, res) { // 1. 創(chuàng)建Vue實例服務(wù)端 const vueApp createSSRApp(App) // 2. 渲染組件 → HTML字符串 const html await renderToString(vueApp) // 3. 返回完整頁面注入渲染出來的html res.send( !DOCTYPE html html body !-- 服務(wù)端渲染生成的HTML -- div idapp${html}/div !-- 客戶端代碼用來水合激活交互 -- script src/client.js/script /body /html ) }) app.listen(3000, () console.log(ssr server 3000))entry-client.js客戶端水合import { createSSRApp } from vue import App from ./App.vue const app createSSRApp(App) // hydrate水合把服務(wù)端靜態(tài)HTML綁定事件變成可交互頁面 app.mount(#app, true)App.vuetemplate div h1Vue SSR頁面/h1 p{{ msg }}/p button clickclickHandle點我/button /div /template script setup const msg 服務(wù)端渲染內(nèi)容 const clickHandle () alert(按鈕交互) /script3. SSR 核心流程用戶請求頁面 → Node 服務(wù)啟動 Vue 應(yīng)用renderToString在服務(wù)端執(zhí)行組件生成靜態(tài) HTML 字符串HTML 直接返回瀏覽器首屏立刻看到內(nèi)容利于 SEO、首屏加載瀏覽器加載客戶端 js執(zhí)行hydrate水合水合對比已有 DOM綁定事件頁面擁有交互能力4. 兩個核心概念區(qū)分SSR服務(wù)端渲染renderToString輸出 HTML 字符串無交互水合 (hydration)客戶端復(fù)用已有 DOM附加事件避免重新創(chuàng)建 DOM5. 極簡面試一句話總結(jié)SSR 在 Node 服務(wù)端運行 Vue 組件通過renderToString將組件編譯為 HTML 返回瀏覽器實現(xiàn)快速首屏展示客戶端執(zhí)行水合為靜態(tài) DOM 綁定交互事件。補充和 SPA 區(qū)別SPA瀏覽器下載 js 后才渲染頁面空白屏 SSR瀏覽器直接收到完整 HTML首屏有內(nèi)容SEO 友好。react項目最簡結(jié)構(gòu)server.js # Node服務(wù) src/ ├── App.jsx # 組件 ├── entry-server.js # 服務(wù)端入口 └── entry-client.js # 客戶端水合入口 index.html # HTML模板1. App.jsxexport default function App() { return ( div h1React SSR Demo/h1 p服務(wù)端渲染出來的文字/p button onClick{() alert(水合成功可以點擊)}點擊測試/button /div ) }2. entry-server.js服務(wù)端渲染代碼import { renderToString } from react-dom/server import App from ./App export function render() { // 將組件渲染成HTML字符串 return renderToString(App /) }3. entry-client.js客戶端水合import { hydrateRoot } from react-dom/client import App from ./App // 復(fù)用服務(wù)端輸出的DOM綁定事件水合 hydrateRoot(document.getElementById(root), App /)4. server.js核心 Node 服務(wù)import express from express import { render } from ./src/entry-server.js const app express() // 托管打包后的客戶端js靜態(tài)資源 app.use(express.static(./dist/client)) app.get(*, async (req, res) { // 1. 服務(wù)端渲染組件得到html字符串 const appHtml render() // 2. 返回完整HTML注入渲染內(nèi)容 引入客戶端水合js const html !DOCTYPE html html body div idroot${appHtml}/div !-- 客戶端打包產(chǎn)物用來水合 -- script src/entry-client.js/script /body /html res.send(html) }) app.listen(3000, () console.log(React SSR 運行在3000))完整執(zhí)行流程瀏覽器訪問頁面 → Node 服務(wù)調(diào)用renderToString(App/)生成靜態(tài) HTML返回 HTML 給瀏覽器頁面直接展示內(nèi)容此時按鈕不能點擊瀏覽器加載entry-client.js執(zhí)行hydrateRoot對比現(xiàn)有 DOM綁定事件頁面擁有交互React SSR 和 Vue3 SSR 關(guān)鍵相同點都需要兩份入口文件服務(wù)端渲染入口、客戶端水合入口服務(wù)端只輸出 HTML 字符串不掛載 DOM客戶端執(zhí)行水合 hydrate復(fù)用已有 DOM添加交互面試高頻區(qū)分? Vue3renderToStringcreateSSRApp().mount(#app, true)? React18renderToStringhydrateRoot