コンテンツにスキップ
ブログに戻る

2020年1月15日 水曜日

Next.js 9.2

投稿者

本日、Next.js 9.2 を発表できることを嬉しく思います。このバージョンには以下の機能が含まれています。

All of these benefits are non-breaking and fully backwards compatible. All you need to do to update is run

ターミナル
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 Modulesをサポートするようになりました。

Next.js 5のnext-cssを使用した以前のサポートとは異なり、グローバルCSSとCSS Modulesは共存できるようになりました。next-cssでは、アプリケーション内のすべての.cssファイルがグローバルまたはローカルとして扱われる必要がありましたが、両方ではありませんでした。

CSS Modulesは、一意のクラス名を自動的に生成することでCSSをローカルスコープにします。これにより、衝突を心配することなく、異なるファイルで同じCSSクラス名を使用できます。

この動作により、CSS ModulesはコンポーネントレベルのCSSを含めるのに理想的な方法となります。CSS Moduleファイルはアプリケーションのどこからでもインポートできます

たとえば、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 Modulesはオプションの機能であり、.module.css拡張子を持つファイルに対してのみ有効になります。通常の<link>スタイルシートグローバルCSSファイルは引き続きサポートされています。

本番環境では、すべてのCSS Moduleファイルは自動的に結合され、多数のミニファイされたコード分割された.cssファイルになります。これらの.cssファイルは、アプリケーションのホット実行パスを表し、アプリケーションのペイントに必要な最小限のCSSがロードされることを保証します。

上記と同様に、この新機能は完全に後方互換性があります。@zeit/next-cssやその他のCSS関連プラグインを使用している場合、競合を避けるために機能は無効になっています。

現在@zeit/next-cssを使用している場合は、next.config.jspackage.jsonからプラグインを削除し、組み込みCSSサポートに移行することをお勧めします。

コード分割戦略の改善

9.2より前のNext.jsバージョンでは、ページをインタラクティブにするためにロードする必要のあるJavaScriptバンドルは固定されていました。

  • ページのJavaScriptファイル
  • 共通JavaScriptを含むファイル
  • Next.jsクライアントサイドランタイムバンドル
  • Webpackクライアントサイドランタイムバンドル
  • 動的インポート(next/dynamicを介して追加され、使用された場合)

ページをインタラクティブにするために、これらのバンドルはすべてロードされる必要があります。ブラウザでReactを起動するために互いに依存しているからです。

アプリケーションがインタラクティブになるためにこれらのバンドルすべてが必要であるため、それらを可能な限り最適化することが重要です。実際には、これはアプリケーションの他の部分からのコードの過剰ダウンロードを避けることを意味します。

このため、Next.jsはページ間で共通のJavaScriptを保持するcommonsバンドルを使用していました。commonsを生成するための古いバンドル分割戦略の計算は、使用率のヒューリスティックでした。モジュールがすべてのページで50%以上使用されている場合、共通モジュールとしてマークされます。それ以外の場合は、ページのJavaScriptファイルにバンドルされます。

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

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

Alex Castleは、多数のファイル、特に多くのページタイプが関与する場合でも、最適化されたcommonsチャンク化を可能にする新しいチャンク化(個別のJavaScriptファイルの作成)の方法を提案しました

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

新しいチャンク化実装は、HTTP/2を活用して、より多くの小さなチャンクを提供します。

新しいヒューリスティックの下では、チャンクは以下のように作成されます。

  • 各ページのための最小限のチャンク。
  • React、ReactDOM、ReactのSchedulerなどを含むフレームワークチャンク。
  • 160KB(ミニファイ/gzip前)を超えるnode_module依存関係のライブラリチャンク。
  • すべてのページで使用されるコードの commons チャンク。
  • 可能な限り多くの共有チャンク(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回以上スターを獲得しています。
  • 220以上の例があるexamplesディレクトリ

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

We are thankful to our community and all the external feedback and contributions that helped shape this release.