简易实现ssr vue31. 项目结构src/ ├── entry-server.js # 服务端入口 ├── entry-client.js # 客户端入口水合 ├── App.vue server.js # Node服务 index.html # HTML模板2. 关键代码server.jsNode 服务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. 创建Vue实例服务端 const vueApp createSSRApp(App) // 2. 渲染组件 → HTML字符串 const html await renderToString(vueApp) // 3. 返回完整页面注入渲染出来的html res.send( !DOCTYPE html html body !-- 服务端渲染生成的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水合把服务端静态HTML绑定事件变成可交互页面 app.mount(#app, true)App.vuetemplate div h1Vue SSR页面/h1 p{{ msg }}/p button clickclickHandle点我/button /div /template script setup const msg 服务端渲染内容 const clickHandle () alert(按钮交互) /script3. SSR 核心流程用户请求页面 → Node 服务启动 Vue 应用renderToString在服务端执行组件生成静态 HTML 字符串HTML 直接返回浏览器首屏立刻看到内容利于 SEO、首屏加载浏览器加载客户端 js执行hydrate水合水合对比已有 DOM绑定事件页面拥有交互能力4. 两个核心概念区分SSR服务端渲染renderToString输出 HTML 字符串无交互水合 (hydration)客户端复用已有 DOM附加事件避免重新创建 DOM5. 极简面试一句话总结SSR 在 Node 服务端运行 Vue 组件通过renderToString将组件编译为 HTML 返回浏览器实现快速首屏展示客户端执行水合为静态 DOM 绑定交互事件。补充和 SPA 区别SPA浏览器下载 js 后才渲染页面空白屏 SSR浏览器直接收到完整 HTML首屏有内容SEO 友好。react项目最简结构server.js # Node服务 src/ ├── App.jsx # 组件 ├── entry-server.js # 服务端入口 └── entry-client.js # 客户端水合入口 index.html # HTML模板1. App.jsxexport default function App() { return ( div h1React SSR Demo/h1 p服务端渲染出来的文字/p button onClick{() alert(水合成功可以点击)}点击测试/button /div ) }2. entry-server.js服务端渲染代码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 // 复用服务端输出的DOM绑定事件水合 hydrateRoot(document.getElementById(root), App /)4. server.js核心 Node 服务import express from express import { render } from ./src/entry-server.js const app express() // 托管打包后的客户端js静态资源 app.use(express.static(./dist/client)) app.get(*, async (req, res) { // 1. 服务端渲染组件得到html字符串 const appHtml render() // 2. 返回完整HTML注入渲染内容 引入客户端水合js const html !DOCTYPE html html body div idroot${appHtml}/div !-- 客户端打包产物用来水合 -- script src/entry-client.js/script /body /html res.send(html) }) app.listen(3000, () console.log(React SSR 运行在3000))完整执行流程浏览器访问页面 → Node 服务调用renderToString(App/)生成静态 HTML返回 HTML 给浏览器页面直接展示内容此时按钮不能点击浏览器加载entry-client.js执行hydrateRoot对比现有 DOM绑定事件页面拥有交互React SSR 和 Vue3 SSR 关键相同点都需要两份入口文件服务端渲染入口、客户端水合入口服务端只输出 HTML 字符串不挂载 DOM客户端执行水合 hydrate复用已有 DOM添加交互面试高频区分✅ Vue3renderToStringcreateSSRApp().mount(#app, true)✅ React18renderToStringhydrateRoot