SSR,俗称 服务端渲染 (Server Side Render),讲人话就是: 直接在服务端层获取数据,渲染出完成的 HTML 文件,直接返回给用户浏览器访问。
非SSR:前后端数据分离,请求到html后再请求了数据,由js将数据填入new dom里 动态更新到html上
痛点:
- 首屏渲染性能瓶颈:
- 空白延迟: HTML下载时间 + JS下载/执行时间 + 请求时间 + 渲染时间。在这段时间内,页面处于空白的状态。
- SEO 问题: 由于页面初始状态为空,因此爬虫无法获取页面中任何有效数据,因此对搜索引擎不友好。
- 虽然一直有在提动态渲染爬虫的技术,不过据我了解,大部分国内搜索引擎仍然是没有实现。
既要保证现有的前端独立的开发模式,又要由服务端渲染,因此我们使用 React SSR。
原理:
- Node 服务: 让前后端运行同一套代码成为可能。
- Virtual Dom: 让前端代码脱离浏览器运行。
条件: Node 中间层、 React / Vue 等框架。 结构大概如下:
server数据脱水
import serialize from 'serialize-javascript'
// 获取数据
const initState = store.getState()
const html = `
<!DOCTYPE html>
<html lang="zh">
<head></head>
<body>
<div id="App"></div>
<script type="application/json" id="SSR_HYDRATED_DATA">${serialize(initState)}</script>
</body>
</html>
`
ctx.status = 200
ctx.body = html
- 使用了serialize-javascript序列化 store, 替代了JSON.stringify,保证数据的安全性,避免代码注入和 XSS 攻击;
- 使用 json 进行传输,可以获得更快的加载速度;
client数据吸水:初始化 store 时,以脱水后的数据为初始化数据,同步创建 store。
const hydratedEl = document.getElementById('SSR_HYDRATED_DATA')
const hydrateData = JSON.parse(hydratedEl.textContent)
// 使用初始 state 创建 Redux store
const store = createStore(reducer, hydrateData)
前后端注入的这个redux inistate是同源的,
问题:如何保证的,前端维护的全局状态,后端是知道的
(因为前端维护的全局数据状态 ,不一定就只有后端的那些数据