鱼和熊掌兼得:Next.js 混合渲染

请订阅「前端向后」这个官方订阅号 «微信公众号» ,即可获得精选自该平台的一套高质量的技术文章。涵盖范围广泛的主题包括但不限于前端开发、Node.js应用开发以及服务端技术相关内容。
写在前面
React 生态中,在单页应用(Single-Page Application, SPA)的支持领域表现最为卓越的是 Next.js,在这一领域表现最为卓越的是 Next.js
SSG(Static Site Generation/Static Generation):static generation, producing static HTML files during the compilation stage.
- SSR(Server-Side Rendering):服务端渲染,用户请求到来时动态生成 HTML
在Next.js中,在CSR启动之前通过多种途径完成页面预渲染是其核心优势之一。这一做法不仅能够显著提升首屏加载速度,并且能够有效优化搜索引擎排名(SEO),充分体现了其技术实力和产品价值。
不仅如此,Next.js 还提供了混用支持,能够将不同渲染模式结合使用,融合互补 ,例如:
ISR(Incremental Static Regeneration):增量静态再生成技术是一种在运行时定期重构并输出静态HTML内容的技术
- SSG 降级 SSR:未命中预先生成的静态 HTML 时,立即进行 SSR
采用静态缓存优化的SSR技术:在完成SSR处理后会将结果存储到缓存中;当该资源再次被请求时会直接从缓存中调用结果;这种机制等效于Server-Sent-Geometry(SSG)。
-
SSG 结合 CSR:编译时生成静态部分(页面外框),CSR 填充动态部分(页面内容)
-
SSR 联动 CSR:URL 直接访问走更快的 SSR,SPA 跳转过来走体验更优的 CSR
这些精致的混合渲染技术让多种渲染模式能够最大限度地发挥各自的优势,并使 Next.js 的性能得到明显提升
SSG + SSR
SSG 类似于将 SSR 的渲染流程提前至编译阶段以消除运行时渲染开销,并带来了极佳的页面加载性能。然而其局限性也很明显——它仅限于渲染静态内容这一应用场景使得这一方法难以发挥更大作用
有。核心问题在于如何界定"静态"与"动态"的概念。它们分别代表信息保持稳定与偶尔变动的状态,并且基本保持稳定的内容我们将其定义为"静态内容"。因此,在采取措施应对信息变动的前提下,则有可能将SSG的有效应用范围扩展到那些变动程度较小但又并非绝对稳定的场景中
在极限情况下,“不频繁更改”与“并非每一次都要更改”是等价的;换句话说,在这种极端情况下,“不经常变动”的含义等同于“并非每次都变动”。也就是说,在所有场景中(除实时/个性化等每时每刻都动态变化的内容),其余场景都可以采用SSG策略(Single-Step Goal),当然,在此前提下必须确保内容能够按照所需频率进行更新并生效。而内容更新的本质就是重新应用SSG策略(Single-Step Goal),因此问题的核心在于确定合适的时机来进行这一操作……
除了显而易见之外的一个限制因素是静态内容的数量。由于编译阶段必须完成所有页面的渲染工作,在这种情况下如果静态数据达到百万级别时,在编译阶段就需要为每条数据单独生成一份HTML文件。尽管如此,在SSG渲染模式下存在一个固有的问题就是编译成本随着内容数量的增加而不断攀升(无论从时间还是机器资源的角度来看)。对于开发者来说这是一个常见的挑战。
当接收一个用户的请求时,在判断内容是否需要更新的基础上决定是利用SSR重新生成还是继续使用上次的结果。
Instead of generating all pages upfront, you can statically create a small subset and fall back to static content for all other pages. If a user requests a page that hasn’t been generated yet..., they'll briefly see a loading indicator before their browser starts rendering it once getStaticProps completes its execution. From this point onward, every request for this specific page will receive its pre-rendered version. The approach draws inspiration from stale-while-revalidate principles to ensure uninterrupted traffic delivery through background-generated processes. This background-generated process provides uninterrupted traffic delivery through persistent storage until completion.
广泛应用于
This guarantees that users consistently enjoy a swift experience while maintaining rapid build processes and the advantages brought by Static Generation.
P.S. 涉及SSG与SSR结合的具体信息,请参阅When is fallback: true useful?以及Incremental Static Reg regeneration
SSG + CSR
相较于采用SSR的技术方案而言
利用SSR扩大应用范围时必须考虑到其带来的成本问题;那么是否有更低成本的方法来实现这一目标呢?
同样地,在用户体验方面不可避免地会有所牺牲。考虑到SSG在静态内容渲染方面的专长 ,通常建议将页面上的静态内容单独处理,并将其交给SSG进行编译生成;而对于动态部分,则可以通过CSR机制来补充完成。
首先,在缺少数据的情况下立即展示页面,并对页面的一部分进行静态生成以实现预渲染功能。此外,在缺少数据时展示缺失数据的状态也是可行的。
然后,在客户端侧获取数据并在可用时进行显示。
SSG 和 CSR 的集成应用,在减少页面加载白屏时间的同时成功规避了 SSR 的额外开销。然而一个明显的缺点是加载体验相较于纯 SSG来说仍有待提升。具体而言由于动态内容需要客户端进行二次渲染才能完整呈现这与一次完整的 SSG 渲染效果相比略显不足因此这种方案更多地体现为一种渐进式的渲染方式
P.S.关于 SSG 与 CSR 结合的更多信息,见Fetching data on the client side
SSR + CSR
SSG、SSR、CSR 三者两两结合,最耐人寻味的可能是这第三种——SSR 结合 CSR
hydrate不算,SSR 与 CSR 还有结合点么?
毫无疑问,在使用SSR技术时能够有效地减少网页加载期间出现的黑屏时间,并且让网页内容一次性完整显示带来愉快的使用体验;相比之下,在依赖客户端环境和存在数据请求滞后问题的情况下使用CSR技术所带来的缺陷则变得无懈可死地糟糕;这使得CSR技术原本的优势被无限放大了
-
无刷新加载内容
-
可根据用户行为预加载
这些优势并未在首屏加载时充分展现;因此,在仅从页面加载性能的角度来看, SSR 在效果上显著优于 CSR, 建议选择其中之一即可, 无需将两者融合使用. 然而, 当我们把视野扩大到用户操作的全流程时, 我们发现 CSR 和 SSR 能够在功能协调性方面实现高度契合:它们能够在用户体验效率、稳定性以及资源利用率等多个关键指标上达成平衡, 这种协同效应远超预期.
*在首屏阶段采用SSR技术,则无论用户通过URL直接访问到的是首页还是二级、三级页面时,在最短时间内确保页面以最快速度呈现。
站内跳转采用 CSRF(CSRF)机制:在后续的交互操作中进行页面切换时,在切换至新内容的过程中实现了无缝切换,并且系统不仅能够预测用户的浏览行为,在切换至目标页面之前就已经加载了相关内容。
即,首屏加载工作交给更快的 SSR 来做,交互过程中让 CSR 大展身手 :
Accessing this page directly causes getServerSideProps to execute at the request time, resulting in the page being pre-rendered with the returned props.
During client-side transitions using next or link actions, or next/router for routing purposes, accessing this page triggers an API call to the server by Next.js. This causes getServerSideProps to execute, returning a JSON object that contains its execution results. This JSON is then utilized for rendering the current page. Since all these operations are managed internally by Next.js once getServerSideProps is properly configured, there's no additional setup required from your end.
Next.js 被设计为支持这种结合方式,并且它会自动生成可视区域内的站内链接的预加载功能。
在背景中加载该页面。默认设置为true。
任何位于视口中(初始状态或通过滚动)的元素将被预加载。
可以通过传递prefetch={false}来关闭此功能。
P.S.关于 SSR 结合 CSR 的更多信息,见Only runs on server-side
支持原创
关注???? + 收藏????(表示对内容的兴趣,请通过微信联系作者:ayqywx)
