Backブログに戻る

Next.js 9.2

Next.js 9.2では、CSSのネイティブサポート、積極的なコード分割、キャッチオール動的ルートなどが導入されました!

本日、Next.js 9.2のリリースを発表できることを嬉しく思います。主な新機能は以下の通りです:

これらの利点はすべて非破壊的で完全な後方互換性があります。更新するには次のコマンドを実行するだけです:

Terminal
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ファイルはアプリケーション全体でグローバルに適用されました。

開発者体験を向上させ、これらの不整合を解決するために、Next.jsにデフォルトでCSSインポートサポートを組み込む作業を開始しました。

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';
 
// このデフォルトエクスポートは新しい`pages/_app.js`ファイルで必要です。
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

スタイルシートは本質的にグローバルであるため、カスタム<App>コンポーネントでインポートする必要があります。これは、グローバルスタイルのクラス名と順序の競合を避けるために必要です。

開発中、この方法でスタイルシートを表現すると、編集時にページ上のスタイルが自動的に更新されます。

本番環境では、すべてのCSSファイルが自動的に1つの最小化された.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を作成します:

/*
他の`.css`や`.module.css`ファイルとの衝突を心配する必要はありません!
*/
.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"
      // インポートされた`styles`オブジェクトのプロパティとして"error"クラスにアクセスする方法に注目してください。
      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はページ間で共通のJavaScriptを保持するcommonsバンドルを使用していました。古いバンドル分割戦略でcommonsを生成するための計算は、使用率ヒューリスティックでした。モジュールがすべてのページの50%以上で使用されている場合、共通モジュールとしてマークされました。それ以外の場合は、ページのJavaScriptファイルにバンドルされました。

しかし、アプリケーションは多くの異なるタイプのページで構成される場合があります。例えば、マーケティングページ、ブログ、ダッシュボードなどです。他のページタイプと比較してマーケティングページの数が多い場合、commonsの計算はマーケティングページに重点を置いた最適化になります。

私たちの目標は、1つのアプリケーション内のすべてのページタイプを最適化することです。

Alex Castleは、新しいチャンキング方法を提案しました。これにより、多くのページタイプが関与している場合でも、複数のファイルで最適化されたcommonsチャンキングが可能になります。

本日、この新しいチャンキング動作がNext.js 9.2でデフォルトで有効になっていることを発表できることを嬉しく思います。Google ChromeチームAlex Castleにこの変更を貢献してくれたことに深く感謝します。この変更は、数週間にわたる研究、ラボテスト、実世界でのテスト、および実装の累積的な努力を反映しています。

新しいチャンキング実装はHTTP/2を活用して、より多くの小さなサイズのチャンクを配信します。

新しいヒューリスティックでは、次のようなチャンクが作成されます:

  • 各ページの最小限のチャンク
  • React、ReactDOM、Reactのスケジューラなどを含むフレームワークチャンク
  • 160kb(事前最小化/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ユーザーに広く採用されました。

動的ルートセグメント機能がカバーしていないケースがまだいくつかありました。

その1つがキャッチオールルートです。例えば、/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回以上スターされました。
  • examplesディレクトリには220以上の例があります。

Next.jsコミュニティには現在13,800人以上のメンバーがいます。参加してください!

このリリースを形作るのに役立ったコミュニティとすべての外部フィードバックと貢献に感謝します。