![]()
2023年,Next.js 13.3正式發布App Router(應用路由)。一個數字:在此之前,React生態里90%的項目還在用React Router寫路由配置表。一年后,Vercel內部數據顯示,新創建的Next.js項目中App Router采用率超過67%。這不是漸進式升級,是把整個路由哲學連根拔起。
文件夾即路由,這句話聽起來像偷懶,實則是把復雜度從代碼里抽出來,摁進文件系統。
從配置地獄到文件約定
傳統React開發的路由是什么體驗?你要寫一份路由配置表,導入組件,定義路徑,處理嵌套,再考慮懶加載。項目大了之后,這份配置表會變成誰都不敢碰的遺產代碼。React Router v6試圖用嵌套路由和loader簡化,但本質沒變:路由邏輯和組件邏輯是兩套東西,你得同時維護。
Next.js App Router的邏輯截然不同。Vercel工程師在官方文檔里寫得很直白:「文件夾就是路由,文件就是UI加行為。」
具體怎么玩?你在app目錄下新建一個about文件夾,里面放page.js,瀏覽器訪問/about,頁面就出來了。沒有導入,沒有注冊,沒有配置對象。項目結構直接映射URL結構,像把網站地圖攤在桌面上。
這種設計偷師自PHP時代的文件路由,但Next.js給它套了現代框架的殼。關鍵差異在于:文件約定不是可選項,是核心機制。你沒法繞過它,也不需要繞過它。
對比數據:一個中等規模的React Router項目,路由配置文件通常在200-400行之間,還不包括路由守衛、懶加載配置和錯誤邊界。同等規模的Next.js App Router項目,這部分代碼為零。
布局的俄羅斯套娃
App Router真正讓開發者換腦的,是layout.js(布局文件)的嵌套機制。
想象你在搭建一個后臺管理系統。頂部導航、左側菜單、中間內容區——傳統做法是用組件組合,或者在高階組件里包裹。狀態管理、數據獲取、樣式隔離,層層嵌套容易變成「wrapper hell(包裹地獄)」。
Next.js的處理方式更像俄羅斯套娃。根目錄的layout.js包裹整個應用,dashboard目錄下的layout.js只包裹該分支,settings再套一層。每一層自動繼承上層布局,又能獨立加載數據、獨立渲染。
代碼層面的體現:layout.js默認是服務端組件(Server Component),可以直接寫數據庫查詢。這意味著你的導航欄數據、用戶信息,在服務端就渲染完成,不需要客戶端JavaScript參與。
一個被低估的細節:布局的嵌套深度沒有硬性限制。Vercel的示例項目里,有團隊做了5層嵌套布局,從全局導航到具體表單的分步向導,每層只負責自己的一畝三分地。這在React Router里需要手動實現Outlet嵌套,還要處理context傳遞。
嵌套布局的真正價值,是把「頁面」這個概念拆解成可組合的層級,而不是扁平的URL對應扁平的組件。
方括號里的動態魔法
動態路由在App Router里的寫法,會讓第一次接觸的開發者愣一下:方括號。
app/blog/[slug]/page.js,這個文件對應/blog/任意字符串的URL。組件里通過props接收params對象,直接解構出slug。沒有useParams鉤子,沒有鉤子意味著沒有客戶端渲染的額外開銷——如果這是個服務端組件的話。
對比React Router的做法:你需要用useParams()獲取參數,這個鉤子只能在客戶端組件運行。如果要做服務端渲染,得額外配置loader,或者在服務端模板里注入初始數據。
Next.js的方括號設計有個副作用:文件系統本身成了路由的文檔。打開app目錄,你能直接讀出網站的所有URL模式,哪些是靜態,哪些是動態,一目了然。新成員入職,不需要翻路由配置表,看文件夾命名就能理解產品結構。
![]()
更隱蔽的優勢在于類型安全。Next.js 14之后,params和searchParams都支持類型推斷。TypeScript能直接提示你slug是string,而不是any。這在傳統路由配置里需要手動定義接口,維護成本隨著路由增長線性上升。
括號里的組織詭計
Route Groups(路由分組)是App Router里最容易被低估的功能。語法是在文件夾名外加圓括號:(auth)。
作用是什么?組織代碼,但不影響URL。比如你把登錄頁和注冊頁放進(auth)文件夾,實際訪問路徑還是/login和/register。括號里的內容被路由系統忽略,只對你和IDE可見。
這個設計解決了一個真實痛點:大型項目的文件結構往往和URL結構打架。你想按功能模塊組織代碼(認證模塊、支付模塊、管理模塊),但URL需要扁平化(/login而不是/auth/login)。Route Groups讓你兩全其美。
實際案例:Vercel Commerce模板里,(store)分組包含所有店鋪頁面,(checkout)分組包含結算流程。兩個模塊有獨立的layout.js,獨立的加載狀態,獨立的錯誤處理,但URL保持簡潔。
圓括號是App Router給開發者的留白:結構可以復雜,但表面必須簡單。
鉤子的邊界與代價
App Router不是萬能藥。它的客戶端導航鉤子——useRouter和usePathname——有明確的限制:只在客戶端組件("use client"標記)里工作。
這個限制經常被新手踩坑。你在服務端組件里調用useRouter,Next.js會拋錯。正確的做法是把交互邏輯拆到客戶端組件,或者直接用Link組件做聲明式導航。
useRouter.push("/dashboard")的用法和React Router類似,但背后的實現不同。Next.js的客戶端導航會復用已加載的布局和數據,而不是整頁刷新。Vercel把這個叫「軟導航」,性能數據上,頁面切換時間比傳統MPA(多頁應用)快40%以上。
代價是心智模型的切換。你得時刻問自己:這段代碼跑在服務端還是客戶端?數據獲取放page.js還是layout.js?App Router把選擇權交還開發者,但選擇本身成了新的負擔。
一個具體數字:Next.js官方調查顯示,遷移到App Router的開發者中,34%認為「服務端/客戶端邊界」是最難適應的概念,超過動態路由和嵌套布局。
文件系統的終極隱喻
回到開頭那個類比:文件夾即路由。這句話的完整版本是,Next.js App Router把路由系統從「需要學習的API」變成了「已經知道的操作系統常識」。
你不需要記住useHistory或useNavigate的用法,不需要理解BrowserRouter和HashRouter的區別。創建文件夾、創建文件、命名規范——這些技能在學會編程之前就已經具備。
這種設計哲學的代價是靈活性。你沒法像React Router那樣自定義路由匹配邏輯,沒法在運行時動態添加路由。但對于90%的Web應用,這種靈活性本就不必要。
2024年,Next.js團隊在一次技術分享中透露:App Router的代碼量比Pages Router(舊版路由)減少約30%,其中大部分來自路由配置和布局邏輯的簡化。
最后一個細節:App Router的文件夾約定和Next.js的緩存策略深度綁定。每個layout.js和page.js都有獨立的緩存鍵,這意味著你可以精確控制哪部分頁面需要重新渲染,哪部分可以從CDN直接返回。這個特性沒有額外配置,是文件結構自帶的副作用。
當你下一次新建Next.js項目,選擇App Router時,真正選擇的是什么?是省掉幾百行路由配置,還是接受一種更克制的開發方式——用文件系統的可見性,替代代碼的靈活性?
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.