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

2018年3月26日月曜日

Next.js 5.1:ページ解決の高速化、環境設定など

投稿者

Next.js 5.1 を発表できることを嬉しく思います。このバージョンでは、環境設定、フェーズ、ソースマップ、および新しい Next.js プラグインのサポートが追加されました。

パフォーマンスの劇的な改善が行われました。ページの解決は 102 倍 速くなり、エラーページはより効率的に読み込まれるようになりました。

アップグレードまたはインストールするには、実行してください。

ターミナル
npm i next@latest react@latest react-dom@latest

Next.js のバージョンアップに加え、`react` と `react-dom` のピア依存関係もアップグレードします。

@zeit/next-css@zeit/next-sass@zeit/next-less@zeit/next-typescript などの next-plugins もアップグレードしてください。

高速なページ解決

Next.js 5.0 のアーキテクチャ変更のおかげで、URL パスに基づいてページを解決するロジックを 簡略化 できました。これらの変更は、@oliviertassinari による リサーチ に基づいています。以前はページの解決に平均 2.347ms かかっていました。新しいロジックでは、同じページを解決するのに平均 0.023ms かかります。これは、Next.js アプリケーションで最も頻繁に呼び出されるメソッドの 1 つで 102 倍 の速度向上です。

Page resolution shown per request. Left is Next.js 5.0, right is Next.js 5.1
リクエストごとのページ解決。左は Next.js 5.0、右は Next.js 5.1

環境設定

典型的な Node.js 環境では、アプリケーションに環境変数を渡すことがよくあります。たとえば、API_URL=https://api.vercel.com node index.js とし、アプリケーションのどこからでも process.env.API_URL を使用できるようにします。

ユニバーサルレンダリングでは、クライアントサイドで process.env は利用できません。そのため、Next 5.1 では新しい機能 publicRuntimeConfigserverRuntimeConfig を導入しました。これらは next.config.js で設定でき、next/config モジュールを使用して利用できるようになります。

next.config.js
module.exports = {
  serverRuntimeConfig: {
    // Will only be available on the server side
    mySecret: 'secret',
  },
  publicRuntimeConfig: {
    // Will be available on both server and client
    staticFolder: '/static',
  },
};

serverRuntimeConfigpublicRuntimeConfig はどちらも next.config.js で定義されます。

pages/index.js
import getConfig from 'next/config';
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
 
console.log(serverRuntimeConfig.mySecret); // Will only be available on the server side
console.log(publicRuntimeConfig.staticFolder); // Will be available on both server and client
 
export default function Index() {
  return (
    <div>
      <img src={`${publicRuntimeConfig.staticFolder}/logo.png`} />
    </div>
  );
}

next/config モジュールからの getConfig メソッドを使用して、設定値を取得します。

エラー処理の改善

以前は、Next.js はページバンドルを読み込む際にサーバーエラーを検出するための特別なエラー処理メカニズムを持っていました。ページバンドルとは、クライアントサイドでページを読み込むためにロードされる JavaScript ファイルのことです。例えば、/_next/-/page/index.js などです。

ビルド ID の不一致などのエラーが発生した場合でも、ページバンドルは 200 HTTP ステータスで提供されていましたが、その内容は Next.js サーバーによって生成されたエラーの JSON 表現でした。これは、ページが 404 であること以外にも依存するクライアントサイドのエラー処理があったためです。このソリューションは、フォールバックをサポートしない静的ファイルホストや CDN にアセットをアップロードしようとするまでは非常にうまく機能していました。

Next.js 5.1 では、エラー処理ロジックを 完全にリファクタリング しました。ページバンドルが 404 HTTP ステータスを返した場合、ルーターはそれを自動的に検出し、ページをリロードして、マルチゾーン 間のナビゲーションを可能にします。

このロジックを書き直すにあたり、ページリロードをトリガーするために主に使われていた Router.onAppUpdated フックを 削除 しました。ページは自動的にリロードされるようになります。

それに加えて、将来のリリースでのエラー回復における回帰を避けるために、開発モードでのエラー回復に関する新しい一連の 統合テスト を追加しました。

フェーズ / 設定関数

@zeit/next-css のような一部の next-plugins は、Next.js が開発モードの場合や next build を実行する場合にのみ必要です。

オブジェクトを即座にエクスポートするのではなく、設定オブジェクトを返す関数をエクスポートできるようになりました。

module.exports = (phase, { defaultConfig }) => config;

ユーザー設定を返す関数をエクスポートする next.config.js

関数をエクスポートすると、Next.js が実行されている phase (開発、本番、ビルド、エクスポートなど) にアクセスできます。これにより、プラグインは必要なときにのみロードされ、デフォルト設定にもアクセスできるようになります。

一般的に使用される定数(フェーズを含む)を保持する新しいモジュール next/constants を導入しました。next/constants

const {PHASE_DEVELOPMENT_SERVER} = require('next/constants')
module.exports = (phase, {defaultConfig}){
  if(phase === PHASE_DEVELOPMENT_SERVER) {
    return { /* development only config options here */ }
  }
 
  return { /* config options for all phases except development here */ }
}

開発フェーズをチェックする next.config.js

本番ソースマップ生成の改善

Next.js 5 でユニバーサル webpack が導入されたことで、next.config.js に数行追加するだけで、本番環境にソースマップを追加するのが簡単になりました。

next.config.js
module.exports = {
  webpack(config, { dev }) {
    if (!dev) {
      config.devtool = 'source-map';
      for (const plugin of config.plugins) {
        if (plugin['constructor']['name'] === 'UglifyJsPlugin') {
          plugin.options.sourceMap = true;
          break;
        }
      }
    }
    return config;
  },
};

next.config.js でソースマップを手動で有効にする

@zeit/next-source-maps をプロジェクトに追加することで、本番ソースマップを自動的に有効にすることができます。next.config.js に以下を追加してください。

const withSourceMaps = require('@zeit/next-source-maps');
module.exports = withSourceMaps();

next.config.js@zeit/next-source-maps を使用してソースマップを有効にする

これにより、app.js を除くすべてのファイルに対してソースマップが出力されるようになります。その理由は、app.js が複数のファイル(manifest.jscommons.js)と webpack プラグインを組み合わせて構成されていたためです。この副作用により、webpack は結合されたファイルのソースマップを生成できませんでした。

プルリクエスト により、app.js ファイルは main.js に置き換えられました。このファイルには、以前 manifest.js および commons.js にコンパイルされていたコードが含まれ、webpack は main.js のソースマップを生成します。ソースマップは自動的に提供されるため、外部のエラー追跡ツールはエラーが検出されたときに実際のファイルと行番号を表示できるようになります。

The source code is shown in the sources panel
ソースコードがソースパネルに表示されます。

新しいプラグイン / 既存プラグインの改善

2 つの新しい公式プラグインを導入しました。 @zeit/next-bundle-analyzer を使用すると、webpack-bundle-analyzer を簡単に設定して、サーバーサイドとクライアントサイドのバンドルを個別に分析できます。

さらに、公式の csslesssass プラグインに関して、ホットリロードとバンドルに関する多くの改善が行われました。例えば、開発モードでのスタイルのちらつきがなくなり、サブコンポーネントのスタイルも反映されるようになりました。

コミュニティ

Next.js コミュニティは GitHub で見つけることができます。最近、Next.js を使用している著名な企業 のリストがそこに投稿されました。スレッドにプロジェクトを自由に投稿してください。

感謝

このリリースにご協力いただいたすべての方々に感謝いたします。コアへの貢献であれ、増え続ける examples ディレクトリ の拡張と改善であれ、皆様のご協力に感謝いたします。

Next.js への貢献を始めたい場合は、good first issue または help wanted ラベルの付いた課題を見つけることができます。

環境設定と新しいエラーページ処理に関する貴重なフィードバックを提供してくださった Trulia に、特別な感謝を申し上げます。