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

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では、新しい機能として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フックを削除しました。これでページは自動的にリロードされます。

これに加えて、開発モードでのエラー回復に関する新しい一連の統合テストを追加し、将来のリリースでのエラー回復の退行を防ぎます。

フェーズ / config関数

next-pluginsの一部、例えば@zeit/next-cssは、Next.jsが開発モードの場合、またはnext buildを実行している場合にのみ必要とされます。

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

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

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

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

フェーズを含む、よく使用される定数を保持する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();

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

これにより、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を簡単に設定して、サーバーサイドとクライアントサイドのバンドルを個別に分析できます。

さらに、公式のcssless、およびsassプラグインについて、ホットリロードとバンドルに関する多くの改善がありました。例えば、開発モードでスタイルが一時的に適用されない「FOUC (Flash of Unstyled Content)」現象はなくなりました。また、サブコンポーネント内のスタイルも適切に認識されるようになりました。

コミュニティ

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

ありがとうございます

このリリースに貢献してくださった皆様に感謝いたします。中核部分への貢献であれ、成長し続けるexamplesディレクトリの拡張と改善であれ、皆様の貢献に感謝申し上げます。

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

環境設定および新しいエラーページ処理に関連する貴重なフィードバックを提供してくれたTruliaに特に感謝いたします。