现代前端框架的渲染模式?前端渲染是什么意思

现代前端框架的渲染模式 原文来源于:稀土掘金技术社区 ;作者:荒山 如有侵权,联系删除 React 发布已经十年了,笔者接触前端差不多也有十年时间了。说实话&#xff0c

原文:稀土掘金技术社区作者:黄山

如有侵权,请联系我们删除。

React 发布已经10 年了,我从事前端工作也快10 年了。说实话,如果没有Head First 系列书籍,我可能不会进入编程领域。

从头部开始

虽然这个系列书的内容现在看来可能已经过时了。

《Head First》系列书籍告诉我,编程对于刚接触该领域的学生来说非常容易理解,并且可以从中获得很大的自信和成就感。这种风格一直影响着我在学习、工作和教学的过程中,它力求把复杂的事物简单化、大众化,提炼出本质。

我认为前端渲染方法在过去10年里经历了三个主要阶段的演变。

无标题

最初的SSR:中,当时并没有分离出前端,通过JSP、ASP、Ruby on Rails、Django等MVC框架下的模板来渲染页面。这个舞台的明星是jQuery

前后端分离:由Node.js发布,是近十年来迄今为止最快的前端开发。 Angular、React、Vue 等框架是前后端分离的典型例子,我认为这是因为它变得越来越流行。事情变得更加复杂。前端可以专注于UI设计和交互逻辑。后端只需要提供API,不需要关心前端的具体实现。

同态前端:近年来,随着云原生、容器技术、无服务器、边缘计算等底层技术能力的日益普及,前端框架的发展势头强劲。它还被扩展到服务器端。前端开始寻求UX和DX之间的平衡

通过这篇文章,你可以了解近几年前端渲染模型的演变。让我们开始吧。

CSR – 客户端渲染

无标题

每个人都熟悉这一点。即前端页面在浏览器中渲染,服务器只是一个静态资源服务器(如nginx)。

最初的HTML 文件只是一个空壳,必须等到JavaScript 包加载并执行后才能与其交互。

优势

易于部署

页面切换和功能交互友好

复杂交互式应用程序开发的理想选择

有缺点

不利于搜索引擎优化

白屏时间长

可能需要复杂的状态管理。直到今天,国家控制的车轮仍在建造中。

SSR – 服务端渲染

无标题

为了解决SEO 和白屏问题,主要框架已开始支持HTML 字符串的服务器端渲染。

SSR 在服务器端执行数据拉取。由于服务器端距离数据源更近,因此拉取数据的速度更快。然而,这并非完全没有副作用。你必须等到服务器端数据准备好,并且TTFB(第一个字节的时间)比CSR要长一点。

SSR只准备初始数据和HTML。事实上,与CSR类似,它需要在浏览器端加载并重新渲染完整的客户端程序(更技术地说,水化/注水)。使DOM 具有交互性。

换句话说,FCP(First Contentful Paint)比CSR更快,但TTI(Time to Interactive)差别不大。它只是让用户更快地看到您的内容。

水化的主要目的是挂载事件处理程序、触发副作用等。

优势

搜索引擎优化友好

用户可以更快地查看内容

有缺点

部署环境要求。需要Nodejs等JavaScript服务器端执行环境

必须包含完整的JavaScript 客户端渲染器。 TTI还有改进的空间

SSG – 静态生成

无标题

对于博客或者公司主页等完全静态的页面,还可以使用SSG静态渲染。

与SSR 的区别在于SSG 在构建时呈现。

与CSR一样,它是静态的,因此不需要任何服务器端渲染运行时,并且可以部署到静态服务器。

VuePress、VitePress、Gatsby 和Docusaurus 等框架都属于SSG 类别。

优势

与SSR相比,它不需要服务器运行时或数据拉取,使得TTFB/FCP等更加复杂。

有缺点

与SSR类似,也有需要Hydrate的客户端渲染程序。对于以内容为中心的网站,您实际上不需要做太多事情,并且您的客户端程序仍然有进一步压缩的空间。

构建时渲染更加麻烦,因为如果内容发生变化就必须重新构建。

ISG – 增量静态生成

无标题

ISG是SSG的升级版本。解决SSG内容更改的麻烦问题。

ISG 在构建时预渲染页面,但有一个额外的服务器端运行时,可以根据特定的过期/刷新策略(通常使用stale-while-revalidate)重新生成页面。

逐渐补水- 逐渐补水

无标题

前面提到,传统的SSR通常需要客户端程序(上图中的Bundle.js)完全加载,并且只能在水合后检索交互页面,导致TTI缓慢。

最直接的解决方案是减小客户端程序的大小。既然如此,自然要考虑使用代码分割技术。这就是渐进水合作用的起源。

如上图所示,通过代码拆分将Foo和Bar提取为异步组件,可以减少主包的大小并提高TTI。

Foo 和Bar 可以在视口可见时、浏览器空闲时或根据某些策略按需加载和水合,例如React Concurrent Mode,它根据交互优先级加载。

React 18 正式支持渐进式水合(官方称为选择性水合)。

观看此视频,了解有关Progress Hydration 的更多信息。

SSR with streaming – 流式 SSR

无标题

这很容易理解。 ChatGPT 已经变得非常流行,尤其是最近。 ChatGPT API 有两种响应模式:常规响应和流式响应。

renderToString 正常响应。换句话说,SSR 会等待完整的HTML 渲染完毕,然后再将第一个字节发送到客户端。

renderToNodeStream 流响应。仅发送渲染的部分。与ChatGPT 聊天消息一样,它们逐字跳转,但虽然接收完整消息所需的时间相似,但用户体验却截然不同。

浏览器可以优雅地处理HTML 流并快速向用户呈现内容,而不是等待空白屏幕。

下图可以让你更直观的感受到两者的区别。

来源:https://mxstbr.com/thoughts/streaming-ssr/

来源:https://mxstbr.com/thoughts/streaming-ssr/

对于常规流式SSR来说,优化的效果可能没有我们想象的那么明显。这是因为框架需要等到数据拉取完成后才开始渲染。因此,除非你有一个相对复杂且较长的HTML 树序列,从上到下渲染需要很长时间,否则效果并不明显。

优势

与常规响应相比,流式响应可以提前TTFB 和FCP,并且浏览器不必等待空闲,可以连续绘制。

有缺点

拉取数据是TTFB/FCP中阻塞的主要原因。针对这个问题,下面的选择性补水就巧妙的解决了这个问题。

Selective Hydration – 选择性水合

无标题

Progressive Hydration 是Progressive Hydration 和SSR with Streaming 的升级版本。主要通过有选择地跳过“慢速组件”并避免阻塞,可以实现更快的HTML 输出,并且流式响应可以完成其工作。

慢速组件通常是需要异步检索数据、体积较大或执行相对复杂计算的组件。

典型的慢速组件是异步数据采集。如果没有开启选择性水合,则会等到所有异步任务完成后才开始输出。它必须准备好才能继续输出。

无标题

您可以使用最新的Next.js(当前为13.4)来演示它。

未启用选择性水合的Demo:

函数延迟(time:号){

返回新的Promise((已解决)=setTimeout(已解决, 时间))

}

/**

* 获取关键数据

*/

函数getCrucialData() {

返回延迟(1000).then(()={

返回{

data: Math.random(),

}

})

}

函数getData(time: 数字) {

返回延迟(时间).then(()={

返回{

data: Math.random(),

}

})

}

const Foo=async ()={

常量数据=等待getData(1000)

divfoo: 返回{data.data}/div

}

const Bar=async ()={

常量数据=等待getData(2000)

divbar: 返回{data.data}/div

}

/**

* 页

*

*/

导出默认的异步函数WithoutSelective() {

//获取关键数据

const importantData=等待getCrucialData()

返回(

分配

h1 未选择/h1

p此页面显示时没有选择性水合。 /p

pcrucial data: {crucialData.data}/p

福/福

酒吧/酒吧

/div

}

结果:浏览器等待响应3 秒。

这意味着只有在所有服务器组件准备就绪后才会输出实际内容。

开启选择性水合非常容易。只需将其包装在Suspend 中即可告诉React 这可能是一个“慢速组件”并允许跳过它。

导出默认的异步函数WithoutSelective() {

//获取关键数据

const importantData=等待getCrucialData()

返回(

分配

h1 未选择/h1

p此页面显示时没有选择性水合。 /p

pcrucial data: {crucialData.data}/p

悬念后备=\’fooloading\’

福/福

/悬念

悬念后备=\’酒吧加载\’

酒吧/酒吧

/悬念

/div

}

接下来我们看一下执行结果。

无标题

显然TTFB 提前了。但是,完整的请求时间保持不变。

一旦Foo 和Bar 准备就绪,Next.js 就会将渲染结果写入流中。你是怎么做到的?

只需查看HTML,您就可以知道:

无标题

对于慢速组件,React 首先渲染挂起后备内容,留下一个槽。

如果继续往下看,您将看到Foo 和Bar 的渲染结果。

无标题

然后用渲染结果替换槽。之后用于补水。

也就是说,在服务器端,Selective Hydration 在SSR With Streaming 的基础上,通过选择性跳过低优先级慢速组件(主要与FCP 等指标相关)来优化TTFB,并提供加速页面显示。

对客户进行选择性水化的过程与渐进式水化相同。

要了解有关选择性补水的更多信息,请查看以下文章:

18: 选择性补水新品

React 18 中新的Suspense SSR 架构

Islands Architecture – 岛屿架构

无标题

这两年,JavaScript已经成为一股小趋势。最值得注意的是Islands Architecture和React Server Component(RSC,React Server Component)。

他们的想法是渲染服务器端并删除不必要的JavaScript。

岛上建筑的主要代表是Astro。如上图,Astro在服务器端渲染后,默认情况下客户端是没有客户端程序和水合过程的。需要JavaScript 扩展来实现动态交互的组件必须显式标记为孤岛。

这类似于渐进补水的含义。但仍然存在很大差异。

孤岛是JavaScript 上下文中的交互式扩展方法。正如Astro 所解释的,您可以将“岛”视为静态(非交互式)HTML 页面中的动态岛。

每个岛屿都独立加载并部分水化。渐进水化是整个树只是延迟水化的一个分支。

岛屿可以独立于框架。

删除JavaScript 可以缓解典型的SSRTTI 问题。但孤岛架构并不能适用于所有场景。换句话说,当静态页面的百分比远高于动态页面的百分比时,删除JavaScript 的好处更大。

React Server Component – React 服务端组件

无标题

在作者看来,React Server Component(RSC)本质上和孤岛架构的目的是一样的:去除JavaScript。只是执行手段不同而已。

这是官方Next.js 文档中的示例图。与岛式架构类似,静态内容建议使用服务器组件(SC),交互增强可使用客户端组件(CC)。

无标题

顾名思义,RSC是一个只能运行在服务器端的组件。让我们快速比较一下两者之间的差异。

服务器组件客户端组件执行环境服务器-服务器+客户端仅客户端服务器组件所依赖的JavaScript 相关程序对客户端不可见。如果在这里实现,“JavaScript Removal”必须打包并分发给客户端。无需补水。支持的asyncYN 支持事件和副作用。

RSC 的好处与React Hooks 之前的功能组件: 类似。它只是一个常规函数,不能使用钩子,没有状态,并且只被调用一次。

有关RSC 的更多信息,请参阅Next.js 文档。 React官方讨论组也是一个直接学习的好地方。

那么它和岛上的建筑相比怎么样呢?

优势

尽管服务器和客户端组件都是React 框架的组件,但它们具有统一的思维模型,但也存在一些差异。

React Server Component 是集成在React 框架下的原生解决方案,支持与Selective Hydration 一起使用。岛屿建筑只是一种建筑模式。

更详细和灵活的组合是可能的。

有缺点

服务器和客户端组件之间仍然存在显着差异,开发人员必须规划服务器和客户端之间的边界。早期起步是有一定门槛的。当然,岛屿上也会出现类似的问题。

总结

这篇文章比较长,所以我总结了这些渲染模式的发展历史和关系。

无标题

技术迭代是有动机和背景的。不建议为了流行而编程。在大多数情况下,“知道发生了什么以及为什么”就足够了。

#以上有关现代前端框架渲染模式的相关内容摘自网络,仅供参考。相关信息请参见官方公告。

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92780.html

(0)
CSDN's avatarCSDN
上一篇 2024年7月4日 下午4:33
下一篇 2024年7月4日 下午4:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注