Nextjs服务端渲染介绍
Nextjs服务端渲染介绍本网站运用nextjs构建,nextjs和vercel自动为我的网页提供了最佳的渲染策略,没有多余配置即实现了多种渲染的策略。
本网站运用nextjs构建,nextjs和vercel自动为我的网页提供了最佳的渲染策略,没有多余配置即实现了多种渲染的策略。例如,本站的主页是SSG(静态渲染的网页),一旦构建之后页面上的数据就不在发生变化,“我的博客”则是SSR页面,可以动态的渲染页面。所以可能出现这样的情况–在“我的博客”中更新了新的文章,而主页上“最新博客”这一览上没有更新,这就是因为主页和“我的博客”使用了不同的渲染方式。而这些渲染方式我没有手动配置,由nextjs自动选择。虽然不需要我们手动配置,但是了解每种渲染方式背后的原理还是有必要的。这篇博客博客介绍下常见的几种渲染策略和他们的用途。其中,我会重点介绍和对比CSR和SSR。
1.早期网页的渲染方式100%SSR
1.早期网页的渲染方式100%SSR早期的网页100%在服务端进行渲染,html文件和数据通常放在一起,例如django, php等传统的后端 缺点很显然,每次点击一个链接网页需要重新加载,并且网页的交互性有限。
2.Ajax的出现和SPA(单页面应用)--CSR(客户端渲染)
2.Ajax的出现和SPA(单页面应用)–CSR(客户端渲染)2010年前后, Ajax技术出现可以保证网页在不重新加载的前提下发送请求,给用户类似于使用一个App的感觉。典型代表就是Angular, React, Vue等前端框架。
在CSR中,客户端首先加载一个html作为框架,之后执行js来渲染UI, 并且请求新的数据。通过使用CSR, 单页面网页也可以有自己的route, 并且每一个route并不指向服务器,这些route是通过客户端的js来管理的。客户端需要的js代码越来越复杂,这也是今天比较常见的前后端分离模式开始的原因。
这种渲染策略的一个缺点是,客户端需要的JS bundle体积巨大,加载时间长,造成长时间的首屏加载 第二个缺点是直到今天,搜索引擎依然难以理解动态路由内的内容,这会导致SEO的权重下降 第三个缺点是,数据请求的代码也包含在这个客户端的js bundle中,有被黑客提取用于攻破服务器的风险
关于CSR的详细加载流程
关于CSR的详细加载流程首先,客户端发送请求后,服务端向客户端发出回应,客户端下载一个巨大的js bundle; 然后浏览器解析这个js bundle,解析完成后,网页上的UI和交互性同时完成。在下载bundle和解析的过程中,会出现较长时间,也就是我们所说的首屏白屏时间。后续的数据请求等都发生在客户端。
3.带水合的SSR(SSR with hydration)
3.带水合的SSR(SSR with hydration)几年以后,,SSR作为一种新的渲染策略被提出。和之前SSR一样,html和数据文件在服务端即完成渲染。不同的是,之后小体积的js接管网页,给予网页一个单页应用的体验。典型代表Nextjs, Nuxtjs, Svelte等 这种渲染方式的缺点是需要额外的服务器来进行服务端渲染
关于SSR with hydration的详细介绍
关于SSR with hydration的详细介绍浏览器向服务端发送请求后,服务端例如Nextjs会获取到所有所需的数据来运行react生成相应的静态界面,并发送到客户端,这时客户端可以清楚的看到网页内容加载好了,首屏时间较短。之后还会发送一个体积较小的js bundle将其水合到原先的html上。 这时,网页的功能就算完全加载完毕。
4.完全的SSR, Nextjs中的sever component
4.完全的SSR, Nextjs中的sever component在Nextjs中,nextjs将SSR提高到了另一高度:即区分client component和sever component
-
client component即是之前提到的SSR方式,先在服务器端渲染html和数据,之后发送一个小的js bundle水合并接管网页
-
sever component则是完全不需要发生任何js bundle, 这使得sever component的表现更进一步,可以让数据请求完全发生在服务端,避免敏感数据泄露在客户端。但是一个明显的缺点就是,sever component完全失去了交互性。比如,react的生命周期,dom事件的监听,窗口大小的监听,一些浏览器的API等等
所以,在Nextjs中,通常结合client component和sever component,以下是Nextjs官方给出的client component和sever component的应用场景
关于Server component
关于Server component现在许多React的第三方库开始区分client component和server component,所以还是有必要了解一下。Server component的数据请求会发生在服务端,这时nextjs的开发者开始搞事了,在nextjs14中推出的use server中直接写sql代码,其安全性存疑,也引来网友嘲讽这些前端开发者过于懒惰,直接省略了API写sql,建议前端开发直通电路板一步到位。。。
5.静态渲染SSG(预渲染策略)
5.静态渲染SSG(预渲染策略)作为一种补充的渲染策略, SSG在构建前端页面时, 会提前渲染html, 然后会分配到CDN服务器(如果有的话),和带水合的SSR类似,在客户端渲染后,有一个水合的过程。典型代表是nextjs, nuxtjs, Svelte等。 这种渲染方式体现在客户端上响应十分迅速,在服务端方面也不需要服务端每次进行大量的渲染工作 这个渲染方式的缺点显而易见,只有在项目构建时才能生成新的内容,所以每次数据更新网站都需要重新部署。
6.增量静态生成ISR
6.增量静态生成ISR为了解决SSG每次手动部署的痛点,ISR被提出。ISR与SSG类似,运用预渲染策略,可以提前构建静态网页,与SSG不同的是,ISR可以自动构建新的静态界面在CDN服务器上。需要程序员手写相应代码来实现这一功能,例如,每隔一定时间重新构建,或者每次检测到数据变化时构建。通过nextjs,可以简单快速的实现ISR。 ISR结合了SSG和SSR的优点,同时避免了二者的缺点。客户端可以快速下载渲染好的静态页面,并且保证数据有一定的动态性,同时服务端不需要消耗大量资源为每次请求渲染相应的页面。 缺点是构建和部署有一定门槛,推荐使用nextjs+vercel可以快速进行部署。
7.群岛渲染Island render
7.群岛渲染Island render在正常的水合过程中,js bundle水合到完整的html页面上,这个过程实际其实并不高效,因为大部分页面的html不需要js来使得他们变得可交互性。一个完整的水合浪费时间,会造成html已经加载,而js还没有水合完成,体现在客户端的表现就是,用户可以看到页面已经加载,但是相应的交互性没有体现,网页好像“冻住”了。 Island的提出即是解决这一问题,在island中,用户一开始看到静态的html界面,然后只在需要交互性的component上水合上js bundle。 提出这一渲染策略的是Astro,在Astro中,还可以在每个island中使用不同的前端框架,一个页面可以是多个框架混用,React, Svelte, Vue等等
8.流式传输Streaming SSR
8.流式传输Streaming SSR同样是为了解决水合的问题,nextjs提出了streaming ssr策略。这个策略允许同时渲染多个component,将每个component的加载–水合等生命周期独立开来,而不是一次渲染。可以避免或减少页面因为水合而产生“冻结”的时间。
9.Resumablity
9.Resumablity水合如此的烦人,尽管各个框架提出不同的优化方案,但是还有更卷的,一个叫qwik的框架提出的resumablity彻底杀死了水合 在这个渲染策略中,事件(交互性)代码被写进了html,
<button on:click="./chunk.js#handler_symbol">click me</button>
在app构建时,需要的js被分为一个个小小的chunk, 任何需要的js会在后台进行懒加载,没有水合的过程发生。 下图是水合过程的示例,以及和resumable application的渲染时间对比 可以看到不需要水合的渲染对比需要水合的渲染响应速度提升非常多。 而水合相比与一开始客户端渲染所需要完整的js bundle也非常多。 如果直接用与对比目前常见的CSR渲染,resumablity提升巨大
10.我的总结
10.我的总结目前大部分网站使用CSR或者SSR的策略,我觉得SSR已经满足目前大部分网站和客户的需求,其他的渲染方式可以先做了解,大部分框架会将这些渲染逻辑封装好,我们只用进行基础的配置。之前的web开发,后端框架一把梭哈,之后CSR的出现带来了前后端分离。近来SSR、SSG、ISR等渲染方式和Nextjs, Nuxtjs这类全栈框架出现,web开发似乎又回到前后端不分的状态,只不过现在前端一把梭哈。。。。