幾個(gè)概念:CSR, SSR, SSG, ISR
首先聊下出現(xiàn)這幾個(gè)概念邮弹,遠(yuǎn)古時(shí)代還是ASP
和JSP
的年代也可以說(shuō)是SSR(Server Side Render)
:服務(wù)端也是直出HTML奥务,隨著瀏覽器能力的增強(qiáng),服務(wù)端將部分渲染邏輯轉(zhuǎn)移到瀏覽器也就是CSR(Client Side Render)
,雖然這種架構(gòu)弱化服務(wù)端要求且更有利于客戶端功能的模塊化赖舟,但無(wú)疑對(duì)SEO
不夠友好,大部分情況下我們還是希望回到SSR
,但前端模塊化的優(yōu)勢(shì)我們也想要淆院,所以依舊是希望能做到node
端跑所有渲染直出HTML,但即時(shí)渲染也還是會(huì)有成本句惯,所以出來(lái)SSG(Static Site Generation)
:在build
期間即生成渲染所需HTML土辩,即時(shí)渲染直接返回build
所生成HTML。但這引入的問(wèn)題當(dāng)然是數(shù)據(jù)時(shí)效性抢野,如果只是一些純靜態(tài)頁(yè)面當(dāng)然沒(méi)問(wèn)題拷淘,但如果頁(yè)面會(huì)返回每個(gè)小時(shí)都會(huì)變化的新聞列表,我們也可以限定這個(gè)生成是增量式
指孤,即控制數(shù)據(jù)有效時(shí)長(zhǎng)启涯,此謂ISR(Incremental Static Regeneration)
。
Next.js怎么渲染?
使用Next.js
可以讓我們非常方便選擇各種渲染模式:
CSR
import { useState, useEffect } from 'react'function Home() { const [data, setData] = useState(null) useEffect(() => { fetch('/api/xxx') .then((res) => res.json()) .then((data) => setData(data)) }, []) if (data === null) return <p>No data</p> return ( <div> // Use data </div> )}
SSR
如果我們?cè)谝粋€(gè)頁(yè)面級(jí)別組件導(dǎo)出一個(gè)名為getServerSideProps
的異步方法逝嚎,那這個(gè)方法就會(huì)在每次請(qǐng)求發(fā)生時(shí)自動(dòng)執(zhí)行用來(lái)作服務(wù)端渲染所需數(shù)據(jù)扁瓢,該方法返回值可以包含幾個(gè)可選字段:
props
這個(gè)字段是用來(lái)存儲(chǔ)組件渲染所需的數(shù)據(jù)信息的,其內(nèi)部的字段可以直接在組件接收到的屬性中直接取值:
function Page({ data }) { // Render data...}export async function getServerSideProps() { const res = await fetch(`https://.../data`) const data = await res.json() return { props: { data } }}export default Page
notFound
當(dāng)服務(wù)端取數(shù)據(jù)過(guò)程發(fā)現(xiàn)取不到就可以讓getServerSideProps
方法返回 notFound: true
用來(lái)返回404狀態(tài)碼及渲染404頁(yè)面
export async function getStaticProps(context) { const res = await fetch(`https://.../data`) const data = await res.json() if (!data) { return { notFound: true, } } return { props: { data } }}
redirect
如果我們不希望繼續(xù)渲染當(dāng)前頁(yè)面而是跳轉(zhuǎn)到其他頁(yè)面补君,比如未登錄用戶訪問(wèn)涉權(quán)限校驗(yàn)頁(yè)面引几,我們可能希望跳轉(zhuǎn)到登錄頁(yè),此時(shí)可以返回:
{ redirect: { destination: '/login', permanent: false, }}
SSG
/ ISR
如果我們?cè)谝粋€(gè)頁(yè)面級(jí)別組件導(dǎo)出一個(gè)名為getStaticProps
的異步方法挽铁,那這個(gè)方法就會(huì)在build階段就會(huì)執(zhí)行該方法生成頁(yè)面伟桅,該方法返回值可以包含幾個(gè)可選字段,其中 props
, notFound
, redirect
用途與上述getServerSideProps
返回值中對(duì)應(yīng)字段用途相同叽掘,我們?nèi)绻皇鞘褂?code>props則頁(yè)面在build階段就已經(jīng)生成楣铁,且該build產(chǎn)物一直有效且直接完成渲染。
如果我們?cè)谑褂渺o態(tài)build的同時(shí)也希望頁(yè)面能適時(shí)重新build也就只需要在返回值增加revalidate
字段表示間隔多少秒就將上次build生成的頁(yè)面設(shè)置成緩存失效更扁。
export async function getStaticProps() { const res = await fetch('https://.../posts') const posts = await res.json() return { props: { posts, }, // Next.js 需要重新調(diào)用當(dāng)前 getStaticProps 方法: // - 當(dāng)接收到一個(gè)請(qǐng)求 // - 距離上次重新調(diào)用當(dāng)前 getStaticProps 方法已經(jīng)過(guò)去超過(guò)了10秒 revalidate: 10, // 單位:秒 }}
小結(jié)
我們發(fā)現(xiàn)這些在其他框架中可能需要較為復(fù)雜處理的不同渲染方式盖腕,在Next.js
中的實(shí)現(xiàn)卻極為簡(jiǎn)單,只需要幾個(gè)異步方法就可以全部搞定浓镜,不得不說(shuō)Next.js
簡(jiǎn)潔易用溃列。