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
檔案 (如果尚未存在)。
接著,匯入 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 支援。
改善的程式碼分割策略
Next.js 9.2 之前的版本有一組固定的 JavaScript 套件,需要載入才能使頁面互動
- 頁面的 JavaScript 檔案
- 包含通用 JavaScript 的檔案
- Next.js 客戶端執行階段套件
- Webpack 客戶端執行階段套件
- 動態匯入 (透過
next/dynamic
新增,如果使用)
為了使頁面互動,所有這些套件都必須載入,因為它們彼此依賴才能在瀏覽器中啟動 React。
因為所有這些套件都是應用程式互動所必需的,所以它們必須盡可能最佳化,這一點非常重要。實際上,這表示不要從應用程式的其他部分過度下載程式碼。
因此,Next.js 使用了一個 commons
套件,其中包含頁面之間通用的 JavaScript。舊的套件分割策略產生 commons
的計算方式是使用率啟發式演算法。如果一個模組在超過 50% 的頁面中使用,它就會被標記為通用模組。否則,它會被捆綁在頁面的 JavaScript 檔案中。
然而,應用程式可能包含許多不同類型的頁面。例如,行銷頁面、部落格和儀表板。如果行銷頁面數量相較於其他頁面類型較多,則通用模組的計算將導致最佳化主要集中在行銷頁面上。
我們的目標是在一個應用程式中針對所有頁面類型進行最佳化。
Alex Castle 提出了一種新的分塊方法 (建立獨立的 JavaScript 檔案),這允許透過多個檔案進行最佳化的通用模組分塊,包括涉及多種類型頁面的情況。
今天,我們很高興宣布這個新的分塊行為在 Next.js 9.2 中預設啟用。我們衷心感謝 Google Chrome 團隊 和 Alex Castle 對於貢獻此變更。此變更反映了數週的研究、實驗室測試、實際測試和實作的累積努力。
新的分塊實作利用 HTTP/2 來傳遞更多數量且尺寸更小的分塊。
在新的啟發式演算法下,分塊是針對以下項目建立的
- 每個頁面的最小分塊。
- 包含 React、ReactDOM、React 的 Scheduler 等的框架分塊。
- 任何超過 160kb (minify/gzip 前) 的
node_module
依賴項的函式庫分塊 - 用於所有頁面的程式碼的通用分塊。
- 盡可能多的共用分塊 (由 2 個或更多頁面使用),以最佳化整體應用程式大小和初始載入速度。
- Next.js 的客戶端執行階段。
- Webpack 執行階段。
讓我們看看這在實際應用程式中的意義
一個早期採用的產業合作夥伴 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 名成員。 加入我們!
我們感謝我們的社群以及所有外部回饋和貢獻,這些都幫助塑造了這個版本。