SPA应用:所有代码都是在前端动态通过js执行之后把dom节点插入到页面里面去的,不利于做SEO优化、性能优化、首屏加载优化。
面试题:
我们一般把渲染形式分为两种:服务端渲染和客户端渲染。
服务端渲染(Server-Side Rendering,SSR)在服务器端将网页内容渲染为完整的HTML,然后发送到客户端浏览器进行显示。
客户端渲染(Client-Side Rendering,CSR)后端返回一个空壳的HTML,html里面所有的内容,都是在浏览器端通过 JavaScript 动态生成页面内容。
特点 | SSR | CSR |
---|---|---|
渲染时机 | 服务端生成完整HTML,浏览器直接渲染 | 浏览器先加载空壳HTML,通过 JavaScript 填充内容 |
首屏速度 | 较快,用户可快速看到内容 | 较慢,需要下载和执行 JavaScript |
SEO友好性 | 高,搜索引擎可直接抓取完整内容 | 低,部分搜索引擎可能无法执行 JavaScript |
优势:
提高首屏渲染速度:用户无需等待 JavaScript 加载和执行即可看到完整内容,显著提升用户体验
SEO优化:搜索引擎可以直接抓取完整的HTML内容,有助于提高网站在搜索结果中的排名。
共享链接时显示预览:在社交媒体上分享链接时,能够正确显示页面预览信息,增加内容的传播性。
挑战:
开发复杂度增加:需要处理服务器端渲染逻辑,涉及Node.js等后端技术,与前端开发结合更加复杂
服务器压力增大:服务器需要承担渲染页面的工作,可能导致性能瓶颈,尤其是在高并发场景下。
状态管理复杂:需要在服务器和客户端之间同步状态,确保数据一致性,避免因状态不同步导致的错误。
spa应用没办法100%重构为SSR的架构形式
前后端同构
预渲染(prerender)
混合式渲染
从零到一架构实现一个SSR(服务器端渲染)框架是一个复杂但有趣的任务。以下是基于React和Vue的现有SSR实践,结合注水和脱水的概念,对设计思路的详细阐述:
1.框架设计目标
• 高性能:快速生成首屏内容,减少首屏加载时间。
• 良好的用户体验:页面交互流畅,与纯客户端渲染无明显差异。
• 易于开发和维护:提供简洁的API,方便开发者快速上手和扩展。
2.核心组件与流程设计
2.1 服务端渲染(脱水)
• 路由匹配:根据请求的URL,匹配对应的组件或页面。这可以通过一个路由配置表来实现,表中定义了URL模式与组件的映射关系。
• 组件渲染:使用renderToString
(React)或renderToString
(Vue)将匹配到的组件渲染为HTML字符串。在这个过程中,可以传递一些上下文信息,如请求的URL参数、用户信息等,以便组件能够根据这些信息进行个性化渲染。
• 数据获取:在渲染组件之前,可能需要从后端API获取数据。可以设计一个数据预取机制,在服务端渲染时提前获取并注入到组件的状态中。
• HTML组装:将渲染好的HTML字符串、预取的数据(以JSON形式嵌入到HTML中)、以及必要的CSS和JavaScript资源组装成一个完整的HTML页面。
• 响应客户端:将组装好的HTML页面发送给客户端。
2.2 客户端渲染(注水)
• 页面加载:客户端浏览器接收到服务端发送的HTML页面后,开始加载页面资源,包括JavaScript和CSS文件。
• 状态恢复:通过hydrateRoot
(React)或new Vue
(Vue)等API,将服务端渲染的静态HTML“注水”为可交互的组件。这个过程会读取服务端嵌入的初始状态,恢复组件的状态,使得客户端渲染的组件与服务端渲染的结果保持一致。
• 数据更新与交互:用户与页面交互时,组件可能会发起新的数据请求,更新状态,并重新渲染。客户端渲染的组件会接管后续的页面更新和交互逻辑。
3.数据管理
• 状态同步:确保服务端和客户端的状态一致是SSR的关键。可以通过在HTML中嵌入一个全局变量来存储初始状态,客户端在初始化时读取这个状态并应用到组件中。
• 数据缓存:为了提高性能,可以实现数据缓存机制。例如,对于一些不经常变化的数据,可以在服务端缓存一段时间,避免每次请求都重新获取。
4.性能优化
• 代码分割:将应用的JavaScript代码分割成多个小块,按需加载。对于首屏渲染不需要的代码,可以延迟加载,减少首屏加载时间。
• 服务端缓存:对服务端渲染的结果进行缓存,对于相同的请求URL和参数,直接返回缓存的HTML页面,减少渲染时间。
• 流式渲染:如果环境支持,可以使用流式渲染API(如React的renderToPipeableStream
或Vue的renderToNodeStream
),边渲染边发送HTML内容给客户端,进一步提高首屏渲染速度。
5.开发者体验
• 热模块替换(HMR):在开发过程中,提供HMR支持,使得开发者在修改代码后能够即时看到效果,无需重新加载整个页面。
• 错误处理:设计良好的错误处理机制,能够在服务端和客户端捕获并处理渲染过程中的错误,提供友好的错误提示信息,帮助开发者快速定位问题。
6.浏览器兼容性
• polyfill:对于一些不支持现代JavaScript特性的旧浏览器,提供必要的polyfill,确保应用在这些浏览器上也能正常运行。
7.安全性
• XSS防护:在服务端渲染过程中,对所有用户输入的数据进行严格的转义和过滤,防止跨站脚本(XSS)攻击。
• CSRF防护:如果应用涉及到用户认证和敏感操作,需要实现CSRF防护机制,确保请求的安全性。
通过以上设计思路,可以构建一个基本的SSR框架,实现服务端渲染和客户端渲染的无缝衔接,提供高性能和良好的用户体验。