欢迎来到Introzo百科
Introzo百科
当前位置:网站首页 > 技术 > 鱼与熊掌兼得:Next.js 混合渲染

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

日期:2023-10-06 05:56

本文转载自微信公众号《前端到后端》,作者安于青阳。转载本文请联系前端和后台公众号。 写在前面 在React生态系统中,Next.js可能拥有最好的SSR支持,但SSR并不是Next.js的全部,它只是它提供的预渲染支持之一: SSG(Static Site Generation/静态生成):静态生成,编译时生成静态HTML SSR(Server-Side Rendering):服务器端渲染,当用户请求进来时动态生成HTML 在CSR开始之前通过多种方式预渲染页面内容,以加快首屏性能并满足SEO的需求。这是Next.js的核心功能 不仅如此,Next.js 还提供了混合支持,可以组合不同的渲染模式,相互补充,例如: ISR(Incremental Static Regenesis):增量静态再生,运行时定期重新生成静态HTML SSG 降级 SSR:错过预生成的静态 HTML 时立即执行 SSR 带静态缓存的SSR:SSR完成后,会将结果缓存起来,下次命中静态缓存时,直接返回(相当于SSG) SSG与CSR结合:编译时生成静态部分(页面框架),CSR填充动态部分(页面内容) SSR联动CSR:URL直接访问速度更快的SSR,SPA跳转访问体验更好的CSR。 这些微妙的混合渲染支持让各种渲染模式能够充分发挥其优势,使 Next.js 成为一个很好的补充。 SSG+SSR SSG相当于将SSR的渲染过程移至编译时,从而优化了这部分耗时的部分,实现了优秀的页面加载性能。但也存在明显的缺陷——它只能用于渲染静态内容,使得原本强大的解决方案很难发挥作用。那么,有没有办法拓展其适用场景呢? 有。关键在于如何理解“静”。静态和动态实际上描述的是内容变化的频率。几乎(从不)永远不会改变或改变频率非常低的内容称为静态内容。因此,只要找到应对内容变化的方法,就有可能将SSG的适用场景从经常不变化的“静态内容”拓展到不经常变化的“动态内容”。在极端情况下,“不经常改变”就相当于“不每次都改变”。也就是说,除了每时每刻动态变化的实时/个性化内容之外,SSG还可以用于其他场景。当然,前提是保证内容能够按要求更新、有效。内容更新其实就是重新SSG,所以更新机会只有一次…… 另一个不太明显的限制是静态内容的数量,因为渲染工作必须在编译时完成。如果有100万条静态数据,就必须编译100万份HTML,编译一次。编译可能需要几天时间……成本(不考虑时间/机器)会随着内容量的增加而不断增加。这是SSG渲染模式固有的问题,似乎无法解决。除非,在编译过程中不会生成完整的页面...... 针对用户请求的SSR可以提供正确的更新时机。同时,SSR作为编译的下游,有机会阻止漏网之鱼。结果,SSG和SSR一拍即合。 SSG仅编译生成少量热点页,其余部分由SSR在运行时生成。当用户请求到来时,根据内容是否需要更新来决定是使用SSR重新生成还是使用最后生成的产品: 相反,您可以静态生成一小部分页面,并对其余页面使用fallback: true。当有人请求尚未生成的页面时,用户将看到带有加载指示器的页面。不久之后,getStaticProps 完成并且页面将使用请求的数据呈现。从现在开始,每个请求同一页面的人都将获得静态预渲染的页面。受 stale-while-revalidate 的启发,后台再生确保流量不间断地提供服务,始终来自静态存储,并且新构建的页面仅在生成完成后才会推送。 这样,SSG拓展了它的适用场景(内容变化大、无穷无尽编译的海量内容),而SSR获得了性能优势(静态缓存): 这确保用户始终拥有快速的体验,同时保留快速构建和静态生成的优势。 附:有关 SSG 和 SSR 组合的更多信息,请参阅 Fallback: true 何时有用?、增量静态再生 SSG + 企业社会责任 与SSR相比,SSG更便宜。它在本地编译以生成静态 HTML。当它托管在Web服务器或CDN上时,您可以享受预渲染带来的加载性能提升。没有应用服务器高昂的机器成本,无需担心SSR在线服务。可用性和运维工作 利用SSR来拓展SSG的应用场景,必须要考虑与之相关的成本问题。那么,有没有一种成本更低的方法呢? 是的,但你必须在体验上做出妥协。由于SSG擅长渲染静态内容,所以不妨将页面上的动态和静态内容分开,让SSG编译生成页面的静态部分,而剩下的动态部分仍然通过CSR填充: 首先,立即显示没有数据的页面。页面的某些部分可以使用静态生成来预渲染。您可以显示缺失数据的加载状态。 然后,在客户端获取数据并在准备好后显示它。SSG与CSR结合,不仅缩短了页面加载的白屏时间,还避免了SSR的额外成本。不过美中不足的是加载体验不如纯SSG。毕竟动态内容(用户可能更关心)需要在客户端渲染两次才能呈现。不像SSG可以一次呈现完整的内容。因此,这种方法带来了更多的体验提升。用户感知到页面加载速度更快,这被视为渐进式渲染模式。 附:有关SSG和CSR结合的更多信息,请参见客户端获取数据 SSR+CSR SSG、SSR 和 CSR 是两个组合的。最有趣的可能是第三种——SSR 与 CSR 的结合。 不算水合物的话,SSR和CSR有什么结合点吗? 当然有。 SSR可以有效缩短页面加载过程中的白屏时间,同时提供一次完整渲染页面内容的流畅体验。相比之下,CSR渲染性能取决于客户端环境,数据请求滞后等缺点变得无限大,以至于掩盖了CSR的亮点优点: 加载内容而不刷新 可以根据用户行为进行预加载 这些优势确实没有体现在首屏加载过程中,所以如果单看页面加载性能,SSR完全胜过CSR。您可以选择其中之一,无需将它们组合起来。但如果我们把视角提升到用户运营的整个流程,我们发现CSR和SSR可以非常和谐地完美结合: SSR首屏加载:无论用户是通过URL直接访问首页还是二级、三级页面,SSR都能让页面尽快出现。 使用CSR进行站内跳转:后续交互操作时的页面跳转将通过CSR无缝加载新内容,甚至可以提前预测用户行为并加载目标页面的内容。 即首屏加载工作交给速度更快的SSR,CSR就可以在交互过程中大显身手了: 当您直接请求此页面时, getServerSideProps 在请求时运行,并且此页面将使用返回的 props 进行预渲染。当您通过 next/link 或 next/router 在客户端页面转换上请求此页面时,Next.js 会向运行 getServerSideProps 的服务器发送 API 请求。它将返回包含运行 getServerSideProps 的结果的 JSON,并且该 JSON 将用于呈现页面。所有这些工作都将由 Next.js 自动处理,因此只要定义了 getServerSideProps,您就无需执行任何额外操作。 Next.js 不仅提供了对这种组合的内置支持,而且还自动在可视区域中预加载站点链接: prefetch – 在后台预取页面。默认为 true。视口中的任何内容(初始或通过滚动)都将被预加载。可以通过传递 prefetch={false} 来禁用预取。 附:有关 SSR 与 CSR 结合的更多信息,请参阅仅在服务器端运行 原文链接:https://www.introzo.com/s/98wxchUHZHcIvfK2pT1DFQ

关灯