2020 年 1 月 15 日,星期三
Next.js 9.2
發佈者我們很高興今天推出 Next.js 9.2,其中包含:
- 內建全域樣式表的 CSS 支援:應用程式現在可以直接導入
.css
檔案作為全域樣式表。 - 內建元件級樣式的 CSS 模組支援:利用
.module.css
慣例,可以在應用程式的任何地方導入和使用局部作用域的 CSS。 - 更優化的程式碼分割策略:Google Chrome 團隊大幅優化了 Next.js 的程式碼分割策略,顯著縮小了客戶端程式碼包的大小。此外,他們還最大限度地提高了 HTTP/2 的利用率,在不影響 HTTP/1.1 效能的情況下提升了頁面載入速度。
- 全方位動態路由:Next.js 的動態路由現在支援全方位路由,可支援各種新的使用案例,例如 CMS 驅動的網站。
所有這些優點都具備向下相容性,不會影響現有功能。您只需執行以下指令即可更新:
npm i next@latest react@latest react-dom@latest
內建 CSS 支援全域樣式表
Next.js 5 透過名為 next-css
的客製化插件引入了 CSS 導入支援,擴展了 Next.js 的功能。
隨著時間推移,我們不斷收到來自公司和 Next.js 使用者的意見回饋,提到他們經常需要將 next-css
加入到他們的應用程式中。
此外,next-css
在導入 CSS 時存在一些限制。例如,您可以在專案的每個檔案中導入一個 CSS 檔案,但這個導入的 CSS 檔案會成為整個應用程式的全域樣式。
為了提升開發體驗並解決這些不一致之處,我們開始著手將 CSS 導入支援直接內建到 Next.js 中。
我們很高興地宣布,Next.js 現在原生支援將樣式表導入到您的應用程式中。
要在您的應用程式中開始使用 CSS 導入功能,請在 pages/_app.js
中導入 CSS 檔案。
例如,假設您的專案根目錄中有一個名為 styles.css
的樣式表。
body {
padding: 20px 20px 60px;
margin: 0;
}
如果還沒有 pages/_app.js
檔案,請建立一個pages/_app.js
檔案。
然後,導入 styles.css
檔案。
import '../styles.css';
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
由於樣式表本質上是全域的,因此必須在自訂的 <App>
元件中導入。這是為了避免全域樣式的類別名稱和順序衝突所必需的。
在開發過程中,以這種方式表達樣式表,讓您的樣式可以在您編輯時自動更新到頁面上。
在生產環境中,所有 CSS 檔案都會自動串接成一個單一的最小化 .css
檔案。這個 CSS 檔案將透過 <link>
標籤載入,並自動注入到 Next.js 產生的預設 HTML 標記中。
這個新功能完全向下相容。如果您正在使用 @zeit/next-css
或其他 CSS 相關插件,則此功能會被停用以避免衝突。
如果您目前正在使用 @zeit/next-css
,我們建議您從 next.config.js
和 package.json
中移除該插件,以便在升級時轉移到內建的 CSS 支援。
內建 CSS 模組,支援元件級樣式
Next.js 現在支援使用 [name].module.css
檔案命名慣例的 CSS 模組。
與先前在 Next.js 5 中使用 next-css
的支援不同,全域 CSS 和 CSS 模組現在可以共存 — next-css
要求應用程式中的所有 .css
檔案都被視為全域或區域,但不能同時兼具。
CSS 模組透過自動建立唯一的類別名稱來在區域範圍內設定 CSS。這讓您可以在不同的檔案中使用相同的 CSS 類別名稱,而不必擔心衝突。
這種特性使 CSS 模組成為包含元件級 CSS 的理想方式。CSS 模組檔案可以在應用程式中的任何位置匯入。
例如,考慮在 components/
資料夾中可重複使用的 Button
元件
首先,使用以下內容建立 components/Button.module.css
/*
You do not need to worry about .error {} colliding with any other `.css` or
`.module.css` files!
*/
.error {
color: white;
background-color: red;
}
然後,建立 components/Button.js
,匯入並使用上述 CSS 檔案
import styles from './Button.module.css';
export function Button() {
return (
<button
type="button"
// Note how the "error" class is accessed as a property on the imported
// `styles` object.
className={styles.error}
>
Destroy
</button>
);
}
CSS 模組是選用功能,僅針對副檔名為 .module.css
的檔案啟用。仍然支援一般的 <link>
樣式表 和 全域 CSS 檔案。
在正式環境中,所有 CSS 模組檔案都會自動串連成多個已縮小且程式碼分割的 .css
檔案。這些 .css
檔案代表應用程式中的熱門執行路徑,確保每頁載入的 CSS 量最少,以便應用程式繪製。
如同上述,這個新功能完全向下相容。如果您正在使用 @zeit/next-css
或其他 CSS 相關外掛程式,則會停用此功能以避免衝突。
如果您目前正在使用 @zeit/next-css
,我們建議您從 next.config.js
和 package.json
中移除該外掛程式,以便改用內建的 CSS 支援。
改進的程式碼分割策略
9.2 之前的 Next.js 版本需要載入一組固定的 JavaScript 捆綁包,才能使頁面具有互動性
- 頁面的 JavaScript 檔案
- 包含通用 JavaScript 的檔案
- Next.js 用戶端執行階段捆綁包
- Webpack 用戶端執行階段捆綁包
- 動態匯入(透過
next/dynamic
新增,使用時)
為了使頁面具有互動性,所有這些捆綁包都必須載入,因為它們彼此依賴才能在瀏覽器中啟動 React。
由於所有這些捆綁包都是應用程式變得具有互動性所必需的,因此盡可能地最佳化它們非常重要。實際上,這意味著不要從應用程式的其他部分過度下載程式碼。
基於這個原因,Next.js 使用了一個 commons
檔案包,其中包含了頁面之間共用的 JavaScript 程式碼。過去產生 commons
檔案包的分割策略是基於使用率的啟發式演算法。如果一個模組在所有頁面中的使用率超過 50%,它就會被標記為共用模組。否則,它就會被捆綁到該頁面的 JavaScript 檔案中。
然而,應用程式可能包含許多不同類型的頁面。例如,行銷頁面、部落格和儀表板。如果行銷頁面的數量相較於其他類型的頁面多很多,那麼 commons 的計算結果將會導致最佳化過於偏重行銷頁面。
我們的目標是在單個應用程式中,針對所有類型的頁面進行最佳化。
Alex Castle 提出了一種新的程式碼區塊化方法(建立獨立的 JavaScript 檔案),允許使用多個檔案進行最佳化的程式碼區塊化,即使應用程式包含許多不同類型的頁面。
今天,我們很高興地宣布,這個新的程式碼區塊化行為在 Next.js 9.2 中預設啟用。我們要特別感謝Google Chrome 團隊以及 Alex Castle貢獻了這項變更。這項變更反映了數週的研究、實驗室測試、實際應用測試和實作的累積成果。
新的程式碼區塊化實作利用了HTTP/2來傳輸更多更小的程式碼區塊。
在新啟發式演算法下,將會建立以下程式碼區塊:
- 每個頁面都有一個最小化的程式碼區塊。
- 一個包含 React、ReactDOM、React 的 Scheduler 等的框架程式碼區塊。
- 針對任何大小超過 160kb(壓縮/gzip 前)的
node_module
依賴項建立程式庫程式碼區塊。 - 一個包含所有頁面共用程式碼的 commons 程式碼區塊。
- 盡可能多地建立共用程式碼區塊(由 2 個或更多頁面使用),以最佳化整體應用程式大小和初始載入速度。
- Next.js 的客戶端執行環境程式碼區塊。
- Webpack 執行環境程式碼區塊。
讓我們來看看這在實際應用程式中代表什麼意義
早期採用 Next.js 的業界合作夥伴 Barnebys® 發現整體應用程式大小減少了 23%。
此外,他們最大的 JS 軟體包減少了 30%——從 605kB 減少到 425kB——而且無需修改任何程式碼。
另一個產業合作夥伴,SumUp®,最大的 JS 軟體包減少了 70%——從 395kB 減少到 122kB——同樣無需修改任何程式碼。
最大的 JavaScript 軟體包
修改前 | 修改後 | 變化量 | |
---|---|---|---|
Barnebys | 605kB | 425kB | 減少 30% |
SumUp | 395kB | 122kB | 減少 70% |
新的分塊行為不僅減少了整體和初始載入大小,還減少了後續的客戶端導覽。 Barnebys® 在六 (6) 次頁面導覽後,載入的 JavaScript 量減少了 87%。
多次客戶端轉換載入的 JavaScript
修改前 | 修改後 | 變化量 | |
---|---|---|---|
Barnebys | 136kB | 18kB | 減少 87% |
這個新行為完全向後相容。您只需升級到最新版本的 Next.js 即可利用此效能改進。
全方位動態路由
在 Next.js 9 版本中,我們引入了動態路由區段,目標是在不需要自定義伺服器的情況下簡化 Next.js 中的動態區段。此功能已被 Next.js 使用者廣泛採用。
但在某些情況下,動態路由區段功能仍無法涵蓋。
其中一種情況是全方位路由。例如,將像 /post/**
這樣的萬用字元作為頁面路由。當您的巢狀結構由內容來源(例如 CMS)定義時,這尤其有用。
您現在可以使用 [...name]
語法建立全方位動態路由。
例如,pages/post/[...slug].js
將會匹配 /post/a
、/post/a/b
、/post/a/b/c
等等。
slug
將會以個別路徑部分的陣列形式提供於路由器查詢物件中。因此,對於路徑 /post/foo/bar
,查詢物件將會是 { slug: ['foo', 'bar'] }
。
社群
我們很高興看到 Next.js 持續成長的採用率。
- 我們已經有超過 880 位獨立貢獻者。
- 在 GitHub 上,該專案已獲得超過 44,000 個星標。
- 範例目錄 擁有超過 220 個範例。
Next.js 社群現在擁有超過 13,800 位成員。加入我們!
我們感謝我們的社群以及所有幫助塑造此版本發行的外部回饋和貢獻。