简易实现ssr

vue3

1. 项目结构

javascript 复制代码
src/
├── entry-server.js  # 服务端入口
├── entry-client.js  # 客户端入口(水合)
├── App.vue
server.js            # Node服务
index.html           # HTML模板

2. 关键代码

server.js(Node 服务)

javascript 复制代码
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 id="app">${html}</div>
        <!-- 客户端代码,用来水合激活交互 -->
        <script src="/client.js"></script>
      </body>
    </html>
  `)
})

app.listen(3000, () => console.log('ssr server 3000'))

entry-client.js(客户端水合)

javascript 复制代码
import { createSSRApp } from 'vue'
import App from './App.vue'

const app = createSSRApp(App)
// hydrate:水合,把服务端静态HTML绑定事件,变成可交互页面
app.mount('#app', true)

App.vue

javascript 复制代码
<template>
  <div>
    <h1>Vue SSR页面</h1>
    <p>{{ msg }}</p>
    <button @click="clickHandle">点我</button>
  </div>
</template>
<script setup>
const msg = '服务端渲染内容'
const clickHandle = () => alert('按钮交互')
</script>

3. SSR 核心流程

  1. 用户请求页面 → Node 服务启动 Vue 应用
  2. renderToString 在服务端执行组件,生成静态 HTML 字符串
  3. HTML 直接返回浏览器,首屏立刻看到内容(利于 SEO、首屏加载)
  4. 浏览器加载客户端 js,执行 hydrate 水合
  5. 水合:对比已有 DOM,绑定事件,页面拥有交互能力

4. 两个核心概念区分

  • SSR(服务端渲染)renderToString,输出 HTML 字符串,无交互
  • 水合 (hydration):客户端复用已有 DOM,附加事件,避免重新创建 DOM

5. 极简面试一句话总结

SSR 在 Node 服务端运行 Vue 组件,通过 renderToString 将组件编译为 HTML 返回浏览器,实现快速首屏展示;客户端执行水合,为静态 DOM 绑定交互事件。

补充:和 SPA 区别

SPA:浏览器下载 js 后才渲染页面,空白屏; SSR:浏览器直接收到完整 HTML,首屏有内容,SEO 友好。

react

项目最简结构

javascript 复制代码
server.js          # Node服务
src/
├── App.jsx        # 组件
├── entry-server.js # 服务端入口
└── entry-client.js # 客户端水合入口
index.html         # HTML模板

1. App.jsx

javascript 复制代码
export default function App() {
  return (
    <div>
      <h1>React SSR Demo</h1>
      <p>服务端渲染出来的文字</p>
      <button onClick={() => alert('水合成功,可以点击!')}>点击测试</button>
    </div>
  )
}

2. entry-server.js(服务端渲染代码)

javascript 复制代码
import { renderToString } from 'react-dom/server'
import App from './App'

export function render() {
  // 将组件渲染成HTML字符串
  return renderToString(<App />)
}

3. entry-client.js(客户端水合)

javascript 复制代码
import { hydrateRoot } from 'react-dom/client'
import App from './App'

// 复用服务端输出的DOM,绑定事件(水合)
hydrateRoot(document.getElementById('root'), <App />)

4. server.js(核心 Node 服务)

javascript 复制代码
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 id="root">${appHtml}</div>
      <!-- 客户端打包产物,用来水合 -->
      <script src="/entry-client.js"></script>
    </body>
    </html>
  `
  res.send(html)
})

app.listen(3000, () => console.log('React SSR 运行在3000'))

完整执行流程

  1. 浏览器访问页面 → Node 服务调用 renderToString(<App/>),生成静态 HTML
  2. 返回 HTML 给浏览器,页面直接展示内容(此时按钮不能点击)
  3. 浏览器加载 entry-client.js
  4. 执行 hydrateRoot,对比现有 DOM,绑定事件,页面拥有交互

React SSR 和 Vue3 SSR 关键相同点

  1. 都需要两份入口文件:服务端渲染入口、客户端水合入口
  2. 服务端:只输出 HTML 字符串,不挂载 DOM
  3. 客户端:执行水合 hydrate,复用已有 DOM,添加交互

面试高频区分

✅ Vue3:renderToString + createSSRApp().mount('#app', true) ✅ React18:renderToString + hydrateRoot

相关推荐
库克克1 小时前
【C++】 unordered_map 与unordered_set
开发语言·c++
顶级自由人1 小时前
【前端菜鸟的补课01】Zod 与 PostgreSQL 全栈数据工程教学
前端·后端·程序员
swipe2 小时前
11|(前端转全栈)购物车不能只存在前端:用户维度数据如何在后端落库
前端·后端·全栈
雪的季节2 小时前
人工智能 AI 5问
开发语言
李迟2 小时前
一种轻量级C++ CSV文件读写库的实现方案
开发语言·c++
meilindehuzi_a2 小时前
Node.js + LangChain.js + Milvus 实战:从 EPUB 入库到《天龙八部》RAG 问答系统
javascript·langchain·node.js
小园子的小菜3 小时前
Java 并发编程:线程安全队列全解 —— 阻塞与非阻塞实现原理及源码深度剖析
java·开发语言
勇往直前plus3 小时前
Vue3(篇四)单页面应用到路由管理
javascript·typescript·前端框架·vue
Y3815326623 小时前
2026 年 7 月,SERP API 调用的稳定性实战:超时、重试、降级
开发语言·数据库·人工智能·php