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

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 のバージョンアップに加えて、ピア依存関係の reactreact-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` を使用して `API_URL` を使用できます。

ユニバーサルレンダリングでは、クライアントサイドで `process.env` は使用できません。そこで、Next 5.1 では新しい機能である `publicRuntimeConfig` と `serverRuntimeConfig` を導入しました。これらは `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',
  },
};

`serverRuntimeConfig` と `publicRuntimeConfig` の両方が `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の不一致など、エラーが発生した場合、ページバンドルはHTTPステータス200で提供されますが、内容はNext.jsサーバーによって生成されたエラーのJSON表現になります。これは、ページが404であるだけでなく、クライアント側のエラー処理がさらに依存していたためです。この解決策はうまく機能していましたが、フォールバックをサポートしていない静的ファイルホストまたはCDNにアセットをアップロードしようとすると問題が発生しました。

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

このロジックの書き換えにおいて、主にページの再読み込みをトリガーするために使用されていたRouter.onAppUpdatedフックを削除しました。これで、ページは自動的に再読み込みされます。

さらに、将来のリリースでのエラー回復の回帰を回避するために、開発モードでのエラー回復に関する新しい統合テストを追加しました。

フェーズ/設定関数

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

設定オブジェクトをすぐにエクスポートする代わりに、設定オブジェクトを返す関数をエクスポートできるようになりました。

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

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

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

フェーズなど、一般的に使用される定数を保持する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は結合されたファイルのソースマップを生成できませんでした。

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

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

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

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

さらに、公式のcsslesssassプラグインにも多くの改善が加えられました。ホットリロードとバンドリングに関する改善です。例えば、開発モードでは、スタイルが適用されていないコンテンツの一時的な表示(Flash of Unstyled Content)がなくなりました。また、サブコンポーネントのスタイルも適切に取得されるようになりました。

コミュニティ

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

謝辞

このリリースに貢献してくださった皆様に感謝申し上げます。コアへの貢献、あるいは常に成長を続けるexamplesディレクトリの拡張と改善、どちらの場合でも感謝いたします。

Next.jsへの貢献を始めたいと考えている方は、good first issueまたはhelp wantedラベルが付いた問題を探してください。

環境設定と新しいエラーページ処理に関する貴重なフィードバックをいただいたTruliaの皆様に、特に感謝いたします。