SSR在Node.js中需手动控制HTML组装与响应流程:用fs.readFileSync读取含占位符的HTML,字符串替换后通过res.send()返回;Express需配置模板引擎才能使用res.render();React/Vue SSR本质是生成HTML字符串并注入初始状态,难点在于数据获取、样式隔离、路由一致性和hydration匹配。

服务端渲染(SSR)在 Node.js 中不是靠某个“开箱即用”的函数自动完成的,而是由你控制模板拼接时机、数据注入方式和响应流程——核心在于 res.send() 或 res.end() 之前,把 HTML 字符串组装好。
用 fs.readFileSync + 字符串替换是最简 SSR 实现
适合静态结构强、变量少的页面,比如带用户名称的欢迎页。不依赖框架,纯原生 Node.js 即可跑通:
- 读取一个含占位符的 HTML 文件,例如
index.html中写Hello, {{name}}
- 用
fs.readFileSync('./index.html', 'utf8')读成字符串 - 调用
.replace(/{{name}}/g, userName)替换内容 - 最后用
res.setHeader('Content-Type', 'text/html')+res.send(htmlStr)
注意:不能用 fs.readFile(异步)直接链式调用,否则 res.send() 会先执行,导致空响应或报错 Error [ERR_HTTP_HEADERS_SENT]。
express 配合 res.render() 需要显式注册模板引擎
Express 默认不内置任何模板引擎,res.render() 报 Error: No default engine was specified 就是因为没设 app.set('view engine', ...):
立即学习“Java免费学习笔记(深入)”;
- 装对应引擎,如
npm install ejs,然后app.set('view engine', 'ejs') - 设视图目录:
app.set('views', path.join(__dirname, 'views')) -
res.render('home', { title: 'My App', user: req.user })才能生效 - 若用
pug,后缀是.pug;用handlebars,需额外配express-handlebars
常见坑:文件扩展名和 view engine 值不一致(比如设了 'ejs' 却传 'home.hbs'),会导致 404 或 ENOENT 错误。
React/Vue 的 SSR 不是“渲染页面”,而是“生成 HTML 字符串”
所谓 React SSR,本质是调用 ReactDOMServer.renderToString() 得到一段 HTML 字符串,再塞进模板里返回给客户端:
- Node 端不能用
ReactDOM.createRoot().render()—— 这是浏览器 API,服务端没有document - 必须用
renderToString(或) renderToPipeableStream()(流式) - 生成的 HTML 要嵌入完整模板中,比如把
$$html$$替换成结果,并补上加载客户端 JS - 状态同步关键:用
window.__INITIAL_STATE__ = {...}注入 JSON,前端启动时读取,避免两次请求
漏掉状态同步或脚本加载逻辑,页面会闪动、交互失效,或者数据对不上。
真正难的不是“怎么把 HTML 发出去”,而是数据获取时机、样式隔离、路由匹配一致性、以及 hydration 时 DOM 树是否完全匹配——这些细节一旦出错,SSR 就退化成白屏或双端不一致。











