当前位置: 首页 > 科技观察

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

时间:2023-03-22 12:47:11 科技观察

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