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

从Next.js看到企业级框架的SSR支持

时间:2023-03-14 00:51:38 科技观察

转载本文请向后联系前端公众号。一、Next.js简介TheReactFrameworkforProduction是一个面向生产的React框架(废话)。提供许多开箱即用的功能,支持静态渲染/服务器渲染,支持TypeScript,支持打包优化,支持按路由预加载等:Next.js为您提供生产所需的所有功能的最佳开发体验:混合静态和服务器渲染、TypeScript支持、智能捆绑、路由预取等。无需配置。其中,完美的静态渲染/服务端渲染支持,让Next.js在React生态中独树一帜2.核心特性如果说Next.js只做一件事,那就是预渲染:默认情况下,Next.js预渲染每一个页面.这意味着Next.js会提前为每个页面生成HTML,而不是全部由客户端JavaScript完成。具体来说,预渲染分为两种方式:SSG(StaticSiteGeneration):也叫StaticGeneration,在编译时生成静态HTMLSSR(Server-SideRendering):也叫ServerRendering,在用户请求时动态生成HTML来了。与SSR相比,Next.js更喜欢SSG,因为它具有更大的性能优势(静态内容可以托管在CDN上,性能提升立竿见影)。所以建议优先考虑SSG,只有在无法满足SSG的情况下才考虑SSR、CSRP.S.CSR、SSR等渲染模式(比如一些编译时无法静态生成的个性化内容),见前面-端渲染方式围绕核心探索预渲染功能,扩展一系列相关支持,如:路由(文件规范,API):多页面的基础页面级预渲染,代码拆分:逻辑增量静态生成:针对大量页面的编译时间预渲染(即静态生成)策略路由预加载:锦上添花国际化(结合路由):锦上添花集成Serverless功能:锦上添花自动polyfill,自定义head标签:友情礼物另外,还提供了一些通用的场景支持:开箱即用(0配置)TypeScriptCSS模块,SassFastRefresh(可靠的HotReload支持)用户真实数据收集分析(页面加载性能,体验评分等)图像组件默认优化3.路由支持Next.js提供了两种不同的路由支持,静态路由和动态路由静态路由静态路由是通过文件规范来约定的,js文件中pages目录被认为是路由(每个静态路由对应一个页面文件),例如:pages/index.js→/pages/blog/index.js→/blogpages/blog/first-post.js→/blog/first-postpages/dashboard/settings/username.js→/dashboard/settings/username动态路由类似,动态路由也要在pages目录下创建一个文件,只是文件名有点不一般:pages/blog/[slug.js→/blog/:slug(/blog/hello-world)pages/[username]/settings.js→/:username/settings(/foo/settings)pages/post/[...all].js→/post/*(/post/2020/id/title)路径中变化的参数由getStaticPaths填充://pages/posts/[id].jsexportasyncfunctiongetStaticPaths(){return{//必须调用路径,值必须是数组paths:[{//每一项必须是这种形式params:{//必须包含idid:'ssg-SSR'}},{params:{id:'pre-rendering'}}],fallback:false}}进一步传给getStaticProps根据参数获取数据,渲染页面:props:{postData}}}//渲染页面exportdefaultfunctionPost({postData}){return({postData.title}

{postData.title}
)}可以理解如先创建工厂页面(如pages/[路由参数1]/[路由参数2].js),然后getStaticPaths填充路由参数,getStaticProps({params})根据参数请求不同的数据,最后数据进入页面组件开始预渲染:4.SSGsupports最简单,同时性能最好的预渲染方式是静态生成(SSG),将组件渲染工作完全前移到编译时:(编译时)获取数据(编译时)渲染组件,生成HTML并将生成的HTML静态资源托管到一个web服务器或者CDN就可以了,既有React工程的优势,也有web的极致性能,那么首先要解决的是如何获取数据的问题。Next.js的做法是集中管理页面依赖的数据://pages/index.jsexportdefaultfunctionHome(props){...}//获取静态数据return{props:...}}其中getStaticProps只在server端执行(根本不会进入clientbundle),返回的静态数据会传递给页面组件(上例中的Home))也就是说,需要提前通过getStaticProps准备好页面所依赖的所有数据。数据准备好后,组件将开始渲染并生成HTMLP。将整个页面所依赖的所有数据组织到一个地方。至于渲染和生成HTML的部分,可以借助React提供的SSRAPI来完成。只要是依赖数据且可以提前获取的页面,理论上都可以编译生成静态HTML,但是随之而来的还有两个问题:数据可能会发生变化,已经生成的静态页面需要更新。数据量可能太多而“永远”无法编译。静态页面几乎不可能创建(编译可能需要长达百年),即使全部生成,产品信息也会不时更新,需要重新生成静态页面:如果您的应用程序有大量依赖于数据的静态页面(想想:一个非常大的电子商务网站)。你想预渲染所有产品页面,但你的构建将永远花费。因此,增量静态再生(IncrementalStaticRegeneration)应运而生ISR支持针对大量无法穷举编译的页面和需要更新的场景,Next.js允许运行时再生(相当于运行时静态):IncrementalStaticRegeneration允许您通过在流量进入时在后台重新呈现它们来更新现有页面。例如:exportasyncfunctiongetStaticProps(){constres=awaitfetch('https://.../posts')constposts=awaitres.json()return{props:{posts,},//设置有效期并启用ISRrevalidate:1,//以秒为单位}}revalidate:1表示运行时(用户请求调用时)尝试重新生成静态HTML,并且每秒最多重新生成一次静态HTML需要一些时间(用户请求正在等待HTML)。过程中有3个选项:fallback:false:不降级,命中未生成静态页面的路由,直接404fallback:true:降级,命中未生成静态页面的路由,先返回降级后的页面(此时props为空,一般显示一个loading),静态生成HTML,同时会为降级页面的CSR生成一个JSON。完成后浏览器获取数据(客户端填写props),渲染完整页面回退:'blocking':nodowngrade,并要求用户请求等待新页面静态时生成结束(其实就是SSR,渲染过程被阻塞,但是生成的HTML会在完成后保留)即结合路由(getStaticPaths)对还没有生成的页面进行降级,例如://pages/index.jsimport{useRouter}from'next/router'functionPost({post}){constrouter=useRouter()//渲染降级页面if(router.isFallback){return
Loading...
}//Renderpost...}exportasyncfunctiongetStaticPaths(){return{paths:[{params:{id:'1'}},{params:{id:'2'}}],//(页面级)降级策略,true表示如果遇到未生成的,先给它一个降级页面,生成完成后客户端会自动更新fallback:true,}}P.S.详见IncrementalStaticRegeneration,和Thefallbackkey然而并不是所有的场景都能愉快的在编译时静态生成通常情况下,如果组件所依赖的数据是动态的,显然不可能在编译时提前获取数据,更谈不上静态生成。对于SSGgetStaticProps,Next.js提供了SSR特定的getServerSideProps(context)://pages/index.jsexportasyncfunctiongetServerSideProps(context){constres=awaitfetch(`https://...`)constdata=awaitres.json()if(!data){return{notFound:true,}}return{props:{},//会作为props传给页面组件}}也是用来获取数据的,和getStaticProps最大的区别是每次请求都是来了就执行,所以可以拿到请求的上下文参数(context)6.总结预渲染如何获取数据的问题,Next.js探索出了独特的路由支持和精巧的SSG、SSR支持。不仅如此,Next.js还提供了鱼和熊掌兼得的混合使用支持。不同渲染模式的组合到底有多厉害,看下一篇分解参考资料PagesDataFetchingCreateaNext.jsApp:教程有点意思vercel/next-learn-starter:ExampleDemo原文链接:https://mp.weixin.qq.com/s/bS9GHni4ecnz9UFi9RD24Q