跳到內容
返回部落格

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 檔案

pages/_app.js
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.jspackage.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 檔案

components/Button.js
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.jspackage.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 套件

之前之後差異
Barnebys605kB425kB30% 更小
SumUp395kB122kB70% 更小

新的分塊行為不僅減少了您的整體和初始載入大小,也減少了後續的客戶端導航。Barnebys® 在六 (6) 次頁面導航後,JavaScript 載入量減少了 87%

多次客戶端轉換載入的 JavaScript

之前之後差異
Barnebys136kB18kB87% 更小

這個新行為完全向後相容。升級到最新版本的 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 名成員。 加入我們!

我們感謝我們的社群以及所有外部回饋和貢獻,這些都幫助塑造了這個版本。