2020年1月15日(水)
Next.js 9.2
投稿者本日、Next.js 9.2 を発表できることを大変嬉しく思います。主な機能は次のとおりです。
- グローバルスタイルシートの組み込みCSSサポート: アプリケーションは、
.css
ファイルをグローバルスタイルシートとして直接インポートできるようになりました。 - コンポーネントレベルスタイルの組み込みCSSモジュールサポート:
.module.css
の慣例を利用して、ローカルスコープのCSSをアプリケーションのどこからでもインポートして使用できます。 - コード分割戦略の改善: Google ChromeチームがNext.jsのコード分割戦略を大幅に最適化し、クライアントサイドのバンドルサイズが大幅に縮小されました。さらに、HTTP/1.1のパフォーマンスを損なうことなくページ読み込み速度を向上させるために、HTTP/2の利用を最大化しました。
- キャッチオール動的ルーティング: 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ファイルはアプリケーション全体でグローバルになりました。
開発者エクスペリエンスを向上させ、これらの不整合を解決するために、Next.jsにCSSインポートサポートをデフォルトで組み込む作業を開始しました。
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はページ間で共通のJavaScriptを保持するcommons
バンドルを使用していました。以前のバンドル分割戦略でcommons
を生成するための計算は、使用率のヒューリスティックでした。モジュールが全ページの50%以上で使用された場合、共通モジュールとしてマークされました。そうでなければ、ページのJavaScriptファイルにバンドルされました。
しかし、アプリケーションはマーケティングページ、ブログ、ダッシュボードなど、さまざまな種類のページで構成されることがあります。他のページタイプと比較してマーケティングページの数が多かった場合、共通モジュールの計算結果はマーケティングページに大きく焦点を当てた最適化になっていました。
私たちの目標は、1つのアプリケーション内のすべてのページタイプを最適化することです。
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ユーザーに広く採用されています。
しかし、動的ルーティングセグメント機能ではカバーしきれないケースもまだいくつかありました。
その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人以上のメンバーがいます。ぜひご参加ください!
このリリースを形作るのに役立ったコミュニティおよびすべての外部からのフィードバックと貢献に感謝いたします。