我們非常興奮地向您介紹 Next.js 9.3,主要功能包括:
- 新一代靜態網站生成 (SSG) 支援:透過新的資料獲取方法實現內建優化的靜態生成。
- 預覽模式:繞過靜態生成頁面以顯示 CMS 中的草稿內容。
- 全域樣式表的內建 Sass 支援:應用程式現在可以直接導入
.scss
檔案作為全域樣式表。 - 元件級樣式的內建 Sass CSS 模組支援:利用
.module.scss
慣例,可以在應用程式中任何地方導入和使用局部作用域的 CSS。 - 404 頁面的自動靜態優化:透過靜態提供 404 頁面提升速度和可靠性。
- 減少 32 kB 的執行時體積:透過強大的優化減少所有 Next.js 應用程式的執行時大小。
- GitHub Discussions 上的 Next.js 社群:您現在可以直接在 GitHub 的 Next.js 儲存庫中討論和提問。
所有這些改進都是非破壞性的且完全向後兼容。您只需執行以下命令即可更新:
新一代靜態網站生成 (SSG) 支援
在構建網站或網頁應用程式時,通常需要在兩種策略之間選擇:靜態生成 (SSG) 或伺服器端渲染 (SSR)。
Next.js 是第一個混合框架,允許您根據每個頁面的需求選擇最適合的技術。
Next.js 9.0 引入了自動靜態優化的概念。當頁面沒有阻塞式資料獲取需求(如 getInitialProps
)時,它將在構建時自動渲染為 HTML。
還有更多情況下,您可能希望在構建時將頁面渲染為靜態 HTML,即使有阻塞式資料獲取需求。例如,由(無頭)內容管理系統 (CMS) 驅動的行銷頁面或網站的部落格部分。
我們與 SSG 和 next export
的重度使用者(如 HashiCorp)合作,並在 Next.js 歷史上討論最多的 RFC 中與社群廣泛討論了正確的約束條件,以創建一種新的統一方式來進行資料獲取和靜態生成。
今天,我們非常興奮地宣布兩個新的資料獲取方法:getStaticProps
和 getServerSideProps
。我們還提供了一種方法來為動態路由的靜態頁面提供參數:getStaticPaths
。
這些新方法比 getInitialProps
模型有許多優勢,因為它們明確區分了 SSG 和 SSR:
getStaticProps
(靜態生成):在構建時獲取資料。getStaticPaths
(靜態生成):根據資料指定要預渲染的動態路由。getServerSideProps
(伺服器端渲染):在每個請求時獲取資料。- 這些改進是 API 的補充。所有新功能完全向後兼容,可以逐步採用。沒有引入任何棄用,
getInitialProps
將繼續按目前方式運作。我們鼓勵在新頁面和專案中採用這些新方法。
getStaticProps
如果您從頁面導出一個名為 getStaticProps
的 async
函數,Next.js 將在構建時預渲染此頁面。這在您想從 CMS 渲染特定靜態頁面時特別有用。
getStaticProps
始終在 Node.js 環境中運行,並且程式碼會自動從瀏覽器打包中進行 tree-shaken,確保發送到瀏覽器的程式碼更少。這樣您就不必擔心資料獲取程式碼在 Node.js 和瀏覽器環境中的執行不一致問題。
這允許您使用任何異步甚至同步的資料獲取技術,包括 fetch
、REST、GraphQL,甚至直接訪問資料庫。
context
參數是一個包含以下鍵的物件:
params
:params
包含使用動態路由的頁面的路由參數。例如,如果頁面名稱是[id].js
,則params
將類似於{ id: ... }
。要了解更多,請查看動態路由文件。您應該將此與getStaticPaths
一起使用,我們稍後會解釋。
以下是一個使用 getStaticProps
從 CMS 獲取部落格文章列表的範例:
何時應該使用 getStaticProps?
在以下情況下應使用 getStaticProps
:
- 渲染頁面所需的資料在使用者請求之前已在構建時可用。
- 資料來自無頭 CMS。
- 資料可以公開緩存(非使用者特定)。
- 頁面必須預渲染(為了 SEO)且速度非常快 —
getStaticProps
生成 HTML 和 JSON 檔案,兩者都可以由 CDN 緩存以提高性能。
要了解更多關於 getStaticProps
的資訊,請參閱資料獲取文件。
getStaticPaths
如果頁面有動態路由並使用 getStaticProps
,則需要定義在構建時需要渲染為 HTML 的路徑列表。
如果您從使用動態路由的頁面導出一個名為 getStaticPaths
的 async
函數,Next.js 將靜態預渲染 getStaticPaths
指定的所有路徑。
paths 鍵(必填)
paths 鍵決定了哪些路徑將被預渲染。例如,假設您有一個使用動態路由的頁面 pages/posts/[id].js
。如果您從此頁面導出 getStaticPaths
並為 paths 返回以下內容:
那麼 Next.js 將在構建時使用 pages/posts/[id].js
中的頁面元件靜態生成 posts/1
和 posts/2
。
請注意,每個 params
的值必須與頁面名稱中使用的參數匹配:
- 如果頁面名稱是
pages/posts/[postId]/[commentId]
,則params
應包含postId
和commentId
。 - 如果頁面名稱使用 catch-all 路由,例如
pages/[...slug]
,則params
應包含slug
,這是一個陣列。例如,如果此陣列是['foo', 'bar']
,則 Next.js 將在/foo/bar
處靜態生成頁面。
fallback 鍵(必填)
getStaticPaths
返回的物件必須包含一個布林值 fallback
鍵。
fallback: false
如果 fallback
為 false
,則任何未由 getStaticPaths
返回的路徑將導致 404 頁面。這在您知道所有路徑將在構建時已知時很有用。
以下是一個預渲染名為 pages/posts/[id].js
的每頁一篇部落格文章的範例。部落格文章列表將從 CMS 獲取並由 getStaticPaths
返回。然後,對於每個頁面,它使用 getStaticProps
從 CMS 獲取文章資料。
fallback: true
如果 fallback
為 true
,則 getStaticProps
的行為會改變,Next.js 將在構建時渲染提供的路徑為 HTML。當路徑在構建時未生成時,它將在使用者請求頁面時按需生成。
這在您的應用程式有許多可以靜態生成的路徑,但您不想僅在構建時生成一部分頁面而導致構建時間增加時非常有用。
觸發頁面生成的用戶將獲得一個後備 HTML,這通常是一個帶有加載狀態的頁面。這樣做的原因是靜態 HTML 可以從 CDN 提供,確保頁面始終快速,即使尚未生成。
以下是一個按需靜態生成額外頁面的範例:
要了解更多關於 getStaticPaths
的資訊,請參閱資料獲取文件。
getServerSideProps
如果從頁面中導出一個名為 getServerSideProps
的 async
函式,Next.js 會在每次請求時渲染此頁面(伺服器渲染 (SSR))。
getServerSideProps
永遠在伺服器端執行,且程式碼會自動從瀏覽器套件中進行 tree-shaken,確保傳送到瀏覽器的程式碼更少。這樣你就不必擔心數據獲取程式碼在伺服器和瀏覽器環境中的執行不一致問題。這在許多情況下能提升效能,因為伺服器通常與數據源有更快的連接速度。同時也透過減少數據獲取邏輯的暴露來增強安全性。
這讓你可以使用任何異步甚至同步的數據獲取技術,包括 fetch
、REST、GraphQL,甚至直接訪問數據庫。
當使用 next/link
在頁面間導航時,Next.js 不會在瀏覽器中執行 getServerSideProps
,而是向伺服器發送請求,伺服器會返回 getServerSideProps
的調用結果。
context
參數是一個包含以下鍵的物件:
params
:如果此頁面使用動態路由,params
包含路由參數。如果頁面名稱是[id].js
,則params
會像{ id: ... }
。了解更多,請查看動態路由文件。req
:HTTP 請求物件。res
:HTTP 響應物件。query
:查詢字符串。
以下是一個使用 getServerSideProps
在請求時獲取數據並渲染的範例:
了解更多關於 getServerSideProps
的內容,請參考數據獲取文件。
預覽模式 (Preview Mode)
正如前文所述,靜態生成 (Static Generation) 在頁面從無頭 CMS (headless CMS) 獲取數據時非常有用。但當你在無頭 CMS 上撰寫草稿並希望立即預覽時,靜態生成就不太理想了。由於輸出是靜態的,預覽變更會變得困難,因為你必須重新生成該靜態頁面。
Next.js 中引入的 getStaticProps
開啟了新的可能性,例如在某些條件下利用 Next.js 的按需渲染能力。
舉例來說,當預覽無頭 CMS 中的草稿時,你可能希望繞過靜態渲染,並按需渲染帶有草稿內容的頁面,而非已發布的內容。你希望 Next.js 僅在這種特定情況下繞過靜態生成。
我們很高興宣布 Next.js 的新內建功能來滿足這一需求:預覽模式 (Preview Mode)。
預覽模式允許用戶繞過靜態生成的頁面,按需渲染(伺服器渲染 (SSR))例如來自 CMS 的草稿頁面。
然而,你不僅限於特定的 CMS 系統。預覽模式直接與 getStaticProps
和 getServerSideProps
整合,因此可以與任何類型的數據獲取解決方案一起使用。
預覽模式在使用 next start
時已經可用,或透過部署到 Vercel Edge Network 無縫使用。
親自試試預覽模式:https://next-preview.vercel.app/
與 CMS 供應商的合作
getStaticProps
允許你從任何數據源獲取數據,包括 CMS 系統。
我們正積極與 CMS 生態系統中的許多關鍵參與者合作,提供與 Next.js 整合的範例和指南。
目前正在積極開發的範例包括:
如果你的公司在 CMS 生態系統中活躍,我們很樂意與你合作!歡迎透過電子郵件或 Twitter 聯繫我們的團隊。
內建 Sass 支援全局樣式表
Next.js 9.2 引入了對全局 CSS 樣式表的內建支援,以取代 next-css
插件,並提供更好的默認值以實現更優化的結果。
發布後不久,我們越來越多的用戶要求整合 Sass 支援,因為許多遷移到 Next.js 的企業都有基於 Sass 的現有設計系統。
在調查 Next.js 插件使用情況時,我們發現約 30% 的 Next.js 應用程式目前使用 next-sass
,相比之下,44% 使用原生 CSS,6% 使用 Less。
此外,next-sass
與 next-css
存在相同的缺失限制。這意味著你可以在專案的每個文件中導入 Sass 文件,但導入的 Sass 文件將對整個應用程式全局有效。
考慮到這些統計數據和反饋,我們很高興地宣布 Next.js 現在內建支援導入 Sass 樣式表。
要在你的應用程式中開始使用全局 Sass 導入,請安裝 sass
:
然後,在 pages/_app.js
中導入 Sass 文件。
例如,假設你的專案根目錄中有一個名為 styles.scss
的樣式表,內容如下:
如果尚未存在,請創建一個 pages/_app.js
文件。然後導入 styles.scss
文件:
由於樣式表本質上是全局的,它們必須在自訂 <App>
組件中導入。這對於避免全局樣式的類名和順序衝突是必要的。
在開發環境中,這種表達樣式表的方式允許你在編輯時自動更新頁面上的樣式。
在生產環境中,所有 Sass 和 CSS 文件將自動串聯成一個壓縮的 .css
文件。此 CSS 文件將透過 <link>
標籤加載,並自動注入到 Next.js 生成的默認 HTML 標記中。
此新功能完全向後兼容。如果你正在使用 @zeit/next-sass
或其他 CSS 相關插件,此功能將被禁用以避免衝突。
如果你目前正在使用 @zeit/next-sass
,我們建議從 next.config.js
和 package.json
中移除該插件,並在升級後轉用內建的 Sass 支援。
內建 Sass CSS 模組支援組件級樣式
Next.js 現在支援使用 [name].module.scss
文件命名約定的 Sass 文件的 CSS 模組。
與之前在 Next.js 5+ 中使用 next-sass
提供的支援不同,全局 Sass 和 CSS 模組現在可以共存 — next-sass
要求應用程式中所有的 .scss
文件都必須作為全局或局部處理,而不能兩者兼有。
CSS 模組透過自動創建唯一的類名來局部作用域 Sass。這讓你可以不同的文件中使用相同的 Sass 類名,而不用擔心衝突。
這種行為使 CSS 模組成為包含組件級 Sass 的理想方式。CSS 模組文件可以在應用程式的任何位置導入。
要在你的應用程式中開始使用 Sass CSS 模組,請確保已安裝 sass
:
現在,假設在 components/
文件夾中有一個可重用的 Button
組件:
首先,創建 components/Button.module.scss
,內容如下:
然後,創建 components/Button.js
,導入並使用上述 CSS 文件:
Sass 文件的 CSS 模組是一個_可選_功能,僅對具有 .module.scss
擴展名的文件啟用。常規的 <link>
樣式表 和 全局 Sass 樣式 仍然支援。
在生產環境中,所有 CSS 模組文件將自動串聯成多個壓縮且代碼分割的 .css
文件。這些 .css
文件代表應用程式中的熱執行路徑,確保為每個頁面加載最少的 CSS 以實現繪製。
與上述相同,此新功能完全向後兼容。如果你正在使用 @zeit/next-sass
或其他 CSS 相關插件,此功能將被禁用以避免衝突。
如果你目前正在使用 @zeit/next-sass
,我們建議從 next.config.js
和 package.json
中移除該插件,從而轉用內建的 Sass 支援。
404 的自動靜態優化
Next.js 9 的發布引入了自動靜態優化 (Automatic Static Optimization) 的概念,當頁面沒有阻塞數據需求時,Next.js 會在構建時自動將頁面生成為靜態 HTML。然而,有一個頁面沒有自動渲染為靜態 HTML:404 頁面。404 頁面沒有自動靜態化的主要原因是 /_error
頁面不僅處理 404,還處理其他錯誤。
考慮到 404 頁面是為不存在的路由渲染的,按需渲染頁面可能會增加成本和伺服器負載。
我們從兩個方面著手讓你更容易取得成功:
- 默認的 Next.js 體驗會生成一個靜態 404 頁面
- 在自訂 404 頁面時,仍確保你最終得到一個靜態頁面
此功能完全向後兼容,因此如果你目前有一個自訂的 pages/_error.js
,它將繼續用於 404 頁面,直到你添加 pages/404.js
。
默認的靜態 404 頁面
當你的應用程式沒有自訂的 pages/_error.js
頁面時,Next.js 會自動靜態生成 404 頁面,並在需要提供 404 時使用該頁面。這會自動發生,無需任何變更。
使用 pages/404.js 自訂 404 頁面
要覆蓋默認的 404 頁面,你現在可以創建一個 pages/404.js
,該頁面仍會在構建時自動靜態優化。如果你的應用程式有此頁面,它將取代 pages/_error.js
來渲染 404。
32+ kB 更小的運行時(15 kB+ Gzip)
Next.js 支援與 React 本身相同的瀏覽器,無需任何配置。這包括 Internet Explorer 11 (IE11) 和所有主流瀏覽器(Edge、Firefox、Chrome、Safari、Opera 等)。
作為此兼容性的一部分,我們還會將你的應用程式編譯為兼容 IE11:這讓你可以安全地使用 ES6+ 語法特性、Async/Await、物件 Rest/Spread 屬性等 — 全部無需任何配置。
此編譯過程的一部分還包括透明地注入必要的功能 polyfill(例如 Array.from
或 Symbol
)。然而,這些 polyfill 僅對不到 10% 的網絡流量 是必要的,大多數情況下是為了支援 IE11。
從 Next.js 9.3 開始,Next.js 會自動加載支援舊版瀏覽器所需的 polyfill,並且僅在這些舊版瀏覽器中加載 polyfill。
實際上,這意味著對於90% 以上的用戶,你的_首次加載_大小將減少 32 kB 或更多。
對於依賴更多瀏覽器功能的大型應用程式,這些大小節省甚至更大。
此優化是完全自動的,無需對應用程式進行任何更改即可利用它!
社群
我們非常高興看到 Next.js 的採用持續增長:
- 我們已有超過 927 位獨立貢獻者。
- 在 GitHub 上,該項目已獲得超過 46,600 次星標。
- 範例目錄 中有超過 226 個範例。
Next.js 社群現在擁有超過 15,250 名成員。社群現在可以在 GitHub 討論區中找到,這是一個供社群討論和提問的新地方!加入我們!
我們感謝我們的社群以及所有幫助塑造此版本的外部反饋和貢獻。
特別感謝 Jeff Escalante 對新數據獲取方法的重大反饋。
非常感謝所有為此版本做出貢獻的人:@arcanis, @lgordey, @ijjk, @martpie, @jaywink, @fabianishere, @dijs, @TheRusskiy, @quinnturner, @timneutkens, @lfades, @vvo, @adithwip, @rafaelalmeidatk, @bmathews, @Spy-Seth, @EvgeniyKumachev, @chibicode, @piglovesyou, @HaNdTriX, @Timer, @janicklas-ralph, @devknoll, @prateekbh, @ethanryan, @MoOx, @rifaidev, @msweeneydev, @motiko, 和 @balazsorban44 的幫助!