昨天看了要怎麼用 Next.js 使用不同的渲染模式,今天我們接著從渲染模式延伸,往不同的角度下去認識 Next.js。
使用 React 的人提到要使用 SSR 時,第一個都會想到使用 Next.js 這套框架,應該也有一些人會覺得用 Next.js 就等於使用了 SSR 這個渲染模式。甚至會覺得 SSR 就是 Next.js 的初始渲染模式,那事實真的是如此嗎?
今天就從觀察 Page Router 和 App Router 的預設渲染模式開始今天的主題吧!
我們先建立兩個專案,分別是 Page Router 和 App Router,並且把初始專案內用來當首頁的內容改為非常單純的檔案內容,如下:
export default function Home() {
return (
<div>
<h1>Hello world!</h1>
</div>
);
}
接著 run dev 後,觀察一下 HTTP request 後,是否有返回完整的 HTML。
結果可以發現到,不論是 Page Router 或 App Router 真的如果們預想的一樣當我們發送出 request 後,會返回完整頁面的 HTML。
Page Router
App Router
這樣可以知道這 Page Router 模式和 App Router 模式預設都不是 CSR,而是 SSR 或者是 SSG。接下來讓我們進一步透過 build 來確認兩個 Router 模式的預設渲染模式各是什麼。
∙ Page Router 的預設渲染模式
當我們在 Page Router 執行 run build 後,可以發現到我們的 index.html 檔案出現在 build 好的資料夾內。由此可以得知 Page Router 預設的渲染模式是 SSG,而不是 SSR。
在 build 的結果中,對應到首頁的那一樣也標示著 static 的圈圈
∙ App Router 的預設渲染模式
在 App Router 執行 run build 後,於.next 資料夾裡面,也一樣有發現到 index.html 的檔案,所以在 App Router 中,在沒有額外的設定時預設的渲染模式也是 SSG。
App Router 的 build 的結果也標示著 static 的圈圈。
透過這個小實驗,我們可以觀察到雖然提到 SSR 就會讓人想到 Next.js,但是 Next.js 預設的渲染模式並不是 SSR,而是 SSG。而且為了頁面的效能,只要頁面中沒有動態需求,Next.js 就會選擇 SSG;一旦偵測到動態渲染需求或是顯式的動態設定,才會切換到 SSR 或 ISR。
觀察了 Page Router 和 App Router 的預設渲染模式後,我們再來了解一下,當 run build 完成後,在 terminal 中標示的 Static 和 Dynamic 是什麼意思。
在 Next.js 中,又會把 Static 稱做是 Static Rendering。這裡的 Static Rendering 的意思不難理解,就如同圖片中標示的敘述,會將內容 prerender 成一個靜態的內容,這就是為什麼當出現 Static 的圈圈標示時,我們就可以知道這個 route 對應到的頁面是用 SSG 來處理。Next.js 會去判定頁面有沒有動態需求或沒有利用顯式設定去改動這個頁面的渲染策略後,來看是不是要使用 Static Rendering 這個策略。
關於 Static Rendering 的這個部分,不論是在 page Router 或是 App Router 都是一樣的意思。
在 Next.js 中,這裡的 Dynamic 就如同字面上所示,也就是依照請求在 server 進行 render 的動作,表示這個路由不使用整頁快取 (Cache)。但是這邊要強調的是這裡的「進行 render」的動作,並不單單指的是在伺服器上產出完整的 HTML,並把這個 HTML 返回到 client 端的這個動作。
廣義來說的話,這裡的 Dynamic Rendering 涵蓋的動作包含:
∙ SSR:對伺服器發出 HTML request,將完整畫面的 HTML 產出後,再透過 response 返回給瀏覽器。
∙ RSC 的產出:將 RSC 轉換成 RSC payload,透過 response 返回給瀏覽器。
簡單來說,就是「每次請求時,都會在伺服器端進行一些對應的動作,不重複使用之前的結果」。也就是說「Dynamic」的意義主要是在表示 render 發生的時間點和是否重複使用結果,而不是單純只說「畫面是 server 產的」。
但這裡要補充一下,這邊提到的不進行快取 (Cache),指的是頁面層級
的部分,不是資料面的部分。
除了 Static 和 Dynamic 這兩個類別會被標示在 build 後的結果外,依照是使用 Page Router 還是 App Router,還有可能會出現以下其他類別的標示,像是「(SSG) prerendered as static HTML (uses getStaticProps)」和「(SSG) prerendered as static HTML (uses generateStaticParams)」等。這裡的標示代表的意思是透過 Page Router 或 App Router 中的指定的 function,在 build 的時候,去獲取資料來使用於頁面的 SSG 的模式。而只標記為 Static 的部分,就是很單純的只有靜態資源的靜態頁面,沒有特別在 build 的時候取得一些資料。
雖然大家提到 Next.js 就會想到 SSR,但 Next.js 其實預設會先以靜態的方式處理頁面,當沒有動態需求的內容時,會以使用 SSG 的渲染方式為主,有動態的需求或顯示設定為動態,才會轉為 SSR 或是 ISR。
在 build 完成之後,可以看到每個路由對應到是 dynamic 還是 static,如果標示為 static,就是在 build 的時候就會先產出一個 HTML,如果是 dynamic 則會在發送 request 的時候,才會產生 HTML,或是 RSC payload 返回給瀏覽器。如果有是被標記為 (SSG) prerendered as static HTML (uses getStaticProps) 或 (SSG) prerendered as static HTML (uses generateStaticParams) 的路由則是有在 build 的階段有透過特定的 function 取得資源來產生頁面。
今天從昨天的渲染模式,往下再看更多 Next.js 更細節的部分,也了解到了 Next.js 並不是預設是 SSR 的模式。以及 Dynamic 和 Static 這個在 build 完成後,在 terminal 被標示出的分類是什麼意思。
明天我們再接著這個主題繼續往下挖深,了解 Next.js 的快取 (Cache) 機制。
官方文件 - Static and Dynamic Rendering
官方文件 - dynamic