React Router アプリサーバー

React Router は、ユーザーが自身のサーバーを所有することを前提に設計されていますが、設定したくない場合は、代わりに React Router アプリサーバーを使用できます。これは、Express で構築された、本番環境対応の基本的な Node.js サーバーです。

設計上、React Router アプリサーバーをカスタマイズするオプションは提供していません。これは、基盤となる express サーバーをカスタマイズする必要がある場合、必要なすべてのカスタマイズを処理するための抽象化を作成するよりも、サーバーを完全に管理していただくことを推奨しているためです。カスタマイズしたい場合は、`@react-router/express` adapter へ移行できます

基盤となる express サーバーの設定は、packages/react-router-serve/cli.ts で確認できます。デフォルトでは、以下の Express middleware を使用しています (デフォルトの動作については、各ドキュメントを参照してください)。

HOST 環境変数

Express アプリのホスト名は process.env.HOST を介して設定でき、この値はサーバー起動時に内部の app.listen メソッドに渡されます。

HOST=127.0.0.1 npx react-router-serve build/index.js
react-router-serve <server-build-path>
# e.g.
react-router-serve build/index.js

PORT 環境変数

環境変数を使用してサーバーのポートを変更できます。

PORT=4000 npx react-router-serve build/index.js

開発環境

process.env.NODE_ENV に応じて、サーバーは開発モードまたは本番モードで起動します。

server-build-path は、`react-router.config.ts` で定義されている serverBuildPath を指す必要があります。

ビルド成果物 (build/, public/build/) のみが本番環境にデプロイされる必要があるため、react-router.config.ts が本番環境で利用可能である保証はありません。そのため、このオプションを使用して、サーバービルドがどこにあるかを React Router に伝える必要があります。

開発環境では、react-router-serve はリクエストごとに require キャッシュをパージすることで、最新のコードが実行されるようにします。これにより、コードにいくつかの影響が出ることがあり、注意が必要です。

  • モジュールスコープ内のすべての値が「リセット」されます

    // モジュールキャッシュがクリアされ、このモジュールが新たにrequireされるため、
    // 各リクエストでリセットされます。
    const cache = new Map();
     
    export async function loader({
      params,
    }: Route.LoaderArgs) {
      if (cache.has(params.foo)) {
        return cache.get(params.foo);
      }
     
      const record = await fakeDb.stuff.find(params.foo);
      cache.set(params.foo, record);
      return record;
    }

    開発環境でキャッシュを保持するための回避策が必要な場合は、サーバーでシングルトンを設定できます。

  • あらゆる モジュールの副作用 はそのまま残ります!これは問題を引き起こす可能性がありますが、いずれにせよ避けるべきでしょう。

    // このモジュールがインポートされた瞬間に実行が開始されます
    setInterval(() => {
      console.log(Date.now());
    }, 1000);
     
    export async function loader() {
      // ...
    }

    このような種類のモジュールの副作用を伴う方法でコードを記述する必要がある場合は、独自の @react-router/express サーバーと、ファイル変更時にサーバーを再起動する `pm2-dev``nodemon` のような開発ツールを設定する必要があります。

本番環境では、これは発生しません。サーバーが起動すれば、それで終わりです。