简易实现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

相关推荐
JeffongTan5 小时前
在LWC中镶嵌VF Page获取用户IP
前端·javascript·salesforce
点心的游戏开发世界5 小时前
GDScript 入门笔记(十一):Lambda 与匿名函数
开发语言·笔记·游戏引擎·godot
不cong明的亚子7 小时前
web live多屏互动平台
javascript·经验分享·音视频
陆枫Larry7 小时前
Astro 是什么
前端
事圆则缓7 小时前
Kotlin 协程完全指南
开发语言·kotlin
我爱写代码i8 小时前
BeLink - 支持生成多种URL 缩短网址PHP源码
开发语言·php·短网址php源码
Java后端的Ai之路8 小时前
20、Python - 备忘录模式
开发语言·人工智能·python·外观模式·备忘录模式
是立不是利9 小时前
写给设计师的 CSS 博客美学指南
前端·css
统计学小王子9 小时前
数学建模国赛倒计时4天——《统计模型精讲(混合效应模型R语言实现)》
开发语言·数学建模·r语言
知无不研9 小时前
c语言中循环的介绍与简单应用
c语言·开发语言·算法·循环·for·while