2025最好的Next.js面試題(一)
最近在面試,就寫一些關於問到的面試題,同時也過一下知識點。
基礎概念
什麼是Next.js?它與React的關係是什麼?
Next.js是一個基於React的全棧開發框架,由Vercel開發和維護。它在React的基礎上提供了額外的功能和優化,如服務器組件(Server Components)、流式渲染(Streaming)、服務器操作(Server Actions)等。
我認為Next.js最大的價值在於它簡化了React應用的開發流程,特別是在處理服務器端渲染和路由方面,使我們能夠構建高性能、SEO友好的應用,而無需從零開始配置複雜的工具鏈。
Next.js 14有哪些主要特性?這些特性如何提升開發體驗?
我認為Next.js 14的主要特性包括:
- React Server Components: 默認使用服務器組件,減少客户端JavaScript體積,提升性能
- App Router: 基於文件夾的路由系統,支持佈局、加載狀態和錯誤處理,簡化路由管理
- 服務器操作(Server Actions): 直接在組件中定義服務器端邏輯,無需創建API路由
- 流式渲染(Streaming): 逐步渲染UI,提高用户體驗和感知性能
- Turbopack: 基於Rust的打包工具,提供更快的開發體驗和熱重載
- 內置優化: 自動圖像、字體和腳本優化,無需額外配置
- SEO優化: 內置元數據API和結構化數據支持,提升搜索引擎可見性
- 國際化路由: 內置的多語言支持,簡化國際化應用開發
- Middleware: 請求處理中間件,實現認證、重定向等功能
這些特性共同提升了開發體驗,使我們能夠更快地構建高性能、可維護的應用。
解釋Next.js的App Router是如何工作的?它與Pages Router有何不同?
App Router是Next.js 13+引入的基於文件夾的路由系統,它使用約定式路由,通過文件夾結構自動創建路由:
- 核心概念: 使用app目錄組織路由結構,每個路由段對應一個文件夾
- 特殊文件約定:
- page.js: 定義路由UI和公開訪問點
- layout.js: 定義共享佈局,可嵌套
- loading.js: 創建加載UI,自動集成Suspense
- error.js: 處理錯誤,自動集成Error Boundary
- not-found.js: 處理404錯誤
- 高級功能:
- 支持嵌套路由和佈局
- 路由組(Route Groups): 使用(groupName)語法組織路由而不影響URL結構
- 平行路由(Parallel Routes): 使用@folder語法在同一頁面顯示多個路由
- 攔截路由(Intercepting Routes): 使用(.)、(..)、(...)語法攔截路由,如模態框
示例結構:app/
├── layout.js # 根佈局
├── page.js # 首頁
├── about/
│ └── page.js # /about 路由
├── blog/
│ ├── layout.js # 博客佈局
│ ├── page.js # /blog 路由
│ └── [slug]/
│ └── page.js # /blog/[slug] 動態路由
與Pages Router相比,App Router的主要區別:
- 服務器組件: App Router默認使用React服務器組件,而Pages Router使用客户端組件
- 佈局系統: App Router提供了更強大的嵌套佈局系統,Pages Router需要使用自定義\_app.js
- 數據獲取: App Router允許在組件中直接使用async/await,Pages Router使用getServerSideProps等函數
- 文件約定: App Router使用page.js表示路由,Pages Router使用index.js或命名文件
- 路由分組: App Router支持路由組、平行路由和攔截路由等高級功能
在實際項目中,App Router提供了更靈活、更強大的路由系統,特別適合構建複雜的應用。
渲染相關
組件的渲染模式和頁面的渲染策略有什麼區別?
這實際很容易搞混和不好理解。
組件渲染模式關注的是單個組件如何被處理和執行,通常的表述是:服務端組件(Server Components)、客户端組件(Client Components)。
頁面渲染策略關注的是整個頁面的生成時機和緩存行為,通常的表述是:靜態站點生成(SSG)、服務器端渲染(SSR)、增量靜態再生成(ISR)、客户端渲染(CSR)。
組件的渲染模式通過什麼指令來標識?
App Router不標識就默認是Server組件,客户端組件使用use client,服務端組件use server。
那是什麼決定了頁面的渲染方式那?
在不強制申明路由段的情況下,由Next的分析工具在打包的時候自己分析的情況下:
- cookies()、headers()、unstable_noStore()等服務端系列Api會強制把頁面設置為SSR渲染,如果在layout下使用,下屬頁面均為SSR。
- 使用服務端請求了在頁面裏,為SRR。
- generateStaticParams函數的使用會使動態路由頁面在構建時預渲染,走SSG,在構建的時候就生成HTML頁面。
- 默認情況下,在不滿足上述條件的頁面會被標記為 "靜態路由(Static)",也相當於構建的時候生成HTML。
如果強制申明路由段的情況下,在Page頁碼下通過約定的字段聲明,會高於打包工具分析。但force-static會導致上面提到的第一種情況的服務端Api結果返空,通常我們只會去設置ISR的重新驗證時間。
你提到了路由段的字段聲明,你知道revalidate如何能無限期緩存嗎?
設為false.
在服務端渲染中流式渲染是為了解決什麼問題?
過去SSR需要等待服務端渲染完畢、組件代碼打包到bundle、完成水合後才能操作。Streaming SSR可以一邊渲染一邊傳輸。
一般怎麼觸發流式渲染?使用場景是什麼?
核心是採用Suspense在渲染的時候用一個佔位符替代,等在服務端請求完畢,再流式傳輸給html,替代之前佔位符,用loading.js、page內的suspense都可以觸發這種流式渲染。
流式渲染特別適合包含多個獨立數據區域的頁面。
當你使用流式渲染的時候,同時要使用動態的MetaData API做SEO,會發生什麼?
流式渲染不會觸發(或者説沒有意義),因為MetaData需要完整的TDK在第一時間就展示,就必須先等待generateMetadata的請求先完成。實驗版本中有streamingMetadata的設置,可以流式傳輸TDK。
當一個'use server'的組件下面嵌套了多個'use client','use client'的組件內容會在服務器返回的document中展示嗎?
當一個標記為'use server'的服務器組件下嵌套了多個標記為'use client'的客户端組件時,這些客户端組件的內容會在服務器返回的初始HTML文檔中展示。
這是因為:
- 服務器渲染過程:服務器組件及其所有子組件(包括客户端組件)都會在服務器上進行初始渲染,生成HTML。
-
客户端組件的特殊處理:對於標記了'use client'的組件,Next.js會:
- 在服務器上渲染其初始HTML
- 將組件的JavaScript代碼分離出來,作為單獨的客户端bundle
- 在HTML中插入必要的標記,以便客户端水合
-
水合(Hydration)過程:當HTML加載到瀏覽器後,React會"水合"這些客户端組件,使它們變為可交互狀態。這個過程會:
- 加載客户端組件的JavaScript
- 將事件監聽器附加到已渲染的HTML元素上
- 建立組件狀態和生命週期
因此,'use client'指令並不意味着組件僅在客户端渲染,而是表示該組件需要在客户端進行水合和交互處理。
服務端組件相關
服務端組件有哪些特性和限制?
服務端組件在服務器上渲染,不發送JavaScript到客户端。適用於不需要客户端交互的UI部分,可以顯著減少JavaScript包大小,可以直接連接數據庫、文件系統或其他後端服務,無需中間API層,內容在服務器端渲染,搜索引擎可以更好地索引頁面內容。
服務端組件不能使用React Hooks、瀏覽器API、事件處理器。不能響應客户端組件的狀態變化,從服務端組件傳遞給客户端組件的props必須是可序列化的(不能是函數或類實例)。
當使用了Server Components我們經常能見到帶着rsc的請求在瀏覽器上,這是什麼?
當我們在瀏覽器開發工具的網絡面板中看到帶有"rsc"的請求時,這些是React Server Components (RSC)的數據流請求。"rsc"代表"React Server Components",這是Next.js和React的服務器組件架構的核心部分。
這些請求的工作原理如下:
- RSC Payload: 這些請求返回的是一種特殊格式的數據,稱為RSC Payload(服務器組件負載)。它包含了服務器組件的渲染結果,以一種React客户端可以理解和處理的格式。
- 流式傳輸: 這些請求通常使用HTTP流(Stream)傳輸數據,允許瀏覽器逐步接收和處理服務器組件的渲染結果,而不必等待整個響應完成。
- 客户端-服務器邊界: 當客户端組件需要渲染服務器組件的子組件時,這些RSC請求會被觸發,建立客户端和服務器之間的通信橋樑。
- 導航和重新渲染: 當用户在應用中導航或觸發需要新服務器組件的操作時,瀏覽器會發出新的RSC請求來獲取更新的組件數據。
這些請求的存在是Next.js的App Router架構工作方式的直接結果。在這種架構中,服務器組件在服務器上渲染,然後將結果發送到客户端,而客户端組件則在瀏覽器中渲染。這種混合渲染模式需要客户端和服務器之間的通信機制,這就是我們看到的RSC請求。
結束
實際上,還有很多有關於Nextjs的面試題是可以問的,關於緩存、Edge Runtime、MetaData、ServerActions...
後面有機會再寫吧,歡迎加羣。