SPA应用:所有代码都是在前端动态通过js执行之后把dom节点插入到页面里面去的,不利于做SEO优化、性能优化、首屏加载优化。

面试题:

- 谈谈你对服务端渲染的理解,之前工作中有没有实践过? 1.官网、门户网站 2.落地页 3.广告页 - 有了解过服务端渲染框架吗,请简单说说核心概念? 1.vue --> Nuxt 2.React --> Next、Remix、waku - 如果让你从零到一架构实现一个SSR框架,请简要说说你的设计思路 注水、脱水 服务端把整个内容解析出来,再把解析出来的内容给到前端 前端把解析出来的内容在通过前端的react进一步处理,这个过程称之为注水和脱水 以react为例核心API 1.服务端:renderToString https://zh-hans.react.dev/reference/react-dom/server 2.客户端:hydrateRoot https://zh-hans.react.dev/reference/react-dom/client vue 1.服务端:renderToString https://cn.vuejs.org/api/ssr#server-side-rendering-api 2.客户端:new Vue

服务端渲染

我们一般把渲染形式分为两种:服务端渲染和客户端渲染。

服务端渲染(Server-Side Rendering,SSR)在服务器端将网页内容渲染为完整的HTML,然后发送到客户端浏览器进行显示。

客户端渲染(Client-Side Rendering,CSR)后端返回一个空壳的HTML,html里面所有的内容,都是在浏览器端通过 JavaScript 动态生成页面内容。

SSR Server --> Rendered HTML --> Browser CSR Server --> Empty HTML + JS --> Browser executes JS --> Rendered HTML

SSR 与 CSR 的区别

特点 SSR CSR
渲染时机 服务端生成完整HTML,浏览器直接渲染 浏览器先加载空壳HTML,通过 JavaScript 填充内容
首屏速度 较快,用户可快速看到内容 较慢,需要下载和执行 JavaScript
SEO友好性 高,搜索引擎可直接抓取完整内容 低,部分搜索引擎可能无法执行 JavaScript

SSR的优势与挑战

优势:

  • 提高首屏渲染速度:用户无需等待 JavaScript 加载和执行即可看到完整内容,显著提升用户体验

  • SEO优化:搜索引擎可以直接抓取完整的HTML内容,有助于提高网站在搜索结果中的排名。

  • 共享链接时显示预览:在社交媒体上分享链接时,能够正确显示页面预览信息,增加内容的传播性。

挑战:

  • 开发复杂度增加:需要处理服务器端渲染逻辑,涉及Node.js等后端技术,与前端开发结合更加复杂

  • 服务器压力增大:服务器需要承担渲染页面的工作,可能导致性能瓶颈,尤其是在高并发场景下。

  • 状态管理复杂:需要在服务器和客户端之间同步状态,确保数据一致性,避免因状态不同步导致的错误。

spa应用没办法100%重构为SSR的架构形式

  • 前后端同构

  • 预渲染(prerender)

  • 混合式渲染

从零到一架构实现一个SSR(服务器端渲染)框架

从零到一架构实现一个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框架,实现服务端渲染和客户端渲染的无缝衔接,提供高性能和良好的用户体验。