🥷

[Next.js] 開発中のページを開発環境でのみ表示し、本番環境のビルドには含めないようにする

2024/03/19に公開

はじめに

この記事について

こんにちは、 @zomysan(Twitter) です。この記事では、Next.js で開発をしているWebアプリケーションのフロントエンドを対象に、開発途中のページをどう扱うかということについて書きます。

新しい機能やリニューアルのための開発を始めてあたらしいページを追加したものの、まだ途中なのでユーザーに見せられる状態ではない、ということはよくあると思います。ユーザーには見せたくないけど、開発環境やステージング環境では確認したい。でも本番環境には出したくない。そういうときどうしたら良いのでしょうか?

この記事の対象

この記事は以下のような人を対象としています。

  • Next.js で Web アプリケーションを実装している
  • 開発中のページを本番環境に露出したくない

まとめ

今回、私は以下のように実現してみました。

  • 開発中のページについて、拡張子を .page.dev.tsx にする
    • 公開済みのページは .page.tsx にする
  • next.config.js で pageExtensions の設定を環境変数によって切り替え、本番環境では .dev.page.tsx をビルドに含めないようにする

ここに至るまでの過程や詳しい内容について書いていきます。

解決策の案

リリースできるようになるまでブランチを分けて開発する

もっともわかりやすく、やりやすい解決策です。メインのブランチ( main )から新しい画面を追加するブランチ( new-feature )を切り、リリースできる状態になったら main にマージしてリリースを行います。

ブランチを切り、リリースする前にマージするという図

直感的でわかりやすいいっぽう、開発が長引いて mainnew-feature の間に大きな乖離が出てくるとコンフリクトなどが辛くなります。こまめに mainnew-feature にマージすれば大丈夫そうですが、他のブランチ other-new-feature が同じく存在しうることを考えると、あまりブランチを長期間生存させるのは望ましくありません。(そもそも、そこまで開発が長期化するというのがマズイというのはありますが)

リンクを繋がないようにする

こちらもシンプルで、ページとしては存在するものの、リンクを貼らなければユーザーの導線としては存在しない、という考え方です。

リンクを貼らなければページを開くことは通常ないが、URLを直打ちすればアクセスできるという図

何がなんでも秘匿したいわけではないのであれば、十分に選択肢として有効です。図にもあるとおり、ユーザーがURLを直打ちすればページにアクセスできてしまいます。URLがわからない場合も、Next.jsの設定次第ではブラウザなどでJavaScriptのソースコードを読めば内容がわかってしまうこともありますので、新機能を隠しておきたいときなどには不向きです。

開発環境でのみページが存在するようにする(今回はこれ)

今回私が採用した方法です。Next.jsの設定を変更することで、本番環境においては開発中のページをビルド自体から外し、完全に存在しないものとして扱います。開発環境では普通にページとしてアクセスできます。

本番環境では開発中のページが存在せず、URLを直打ちしてもアクセスできないという図

リリースしてもこのページはビルドに含まれない(JavaScriptのソースコードにも含まれない)ので、開発途中でリリースに含まれても大丈夫です。

おまけ:リリースするときだけ対象ページを手動で削除して、リリースが終わったら戻す

あまりにもシンプルな解決策ですが、暫定的な対応ならこれでもアリかもしれません。ただし、リリースのたびにそのような手順が必要になると面倒ですし、忘れるというリスクもあります。そもそもリリースの前にソースコードを触るというのが怖いですよね。あまりおすすめできません。

Next.js の pageExtensions について

では、ここからは具体的に、どうやって開発中のページを本番環境でのみビルド対象から外すのか、ということについて見ていきます。まずは Next.js の設定のひとつ、 pageExtensions を触ってみましょう。

pageExtensions とは

Next.js では、 /pages 以下に置かれたファイルひとつひとつをページとみなし、ファイル構造と同じルーティングを生成してくれます。これについて、「何をページとしてみなすのか?」を指定するのが pageExtensions です。

https://nextjs.org/docs/pages/api-reference/next-config-js/pageExtensions

pageExtensions のカスタム例

デフォルトでは .ts, .tsx, .js, .jsx がページとしてみなされます。が、 Colocation (関連するコードを近くに置く)の考え方に基づいてファイルを構成していると、 pages にページ本体以外のファイルも置きたくなってくると思います。例えば、以下のようなものです。

  • ページから使うコンポーネント(.tsx など)
  • ページから参照している画像(.png, .svg など)
  • ページの単体テスト(.spec.ts, .test.ts など)
  • ページのスタイルシートのファイル(.css, .scss など)
  • etc...

これらのページじゃないけどページに必要なファイルたちと、実際にルーティングに含めてほしいページ本体を区別するために pageExtension の設定を変更できます。ページ本体の拡張子を .page.tsx にし、pageExtension を以下のように変更します。

next.config.js
module.exports = {
  pageExtensions: ['page.tsx'],
}

こうすることで、コンポーネントや単体テストがルートに含まれなくなります!このような設定を採用しているプロジェクトは多いのではないでしょうか。

開発環境と本番環境で pageExtensions を切り替える

それでは、この pageExtensions を使って実際に本番環境で開発中のページが表示されないようにしてみましょう。

具体的なファイル構成例

以下のようなファイル構成を例にとって説明します。このうち、 src/pages/mypage/config/index.page.tsx が今回開発していきたいページです。

ファイル構成
.
├── src/
│   └── pages/
│       ├── index.page.tsx
│       ├── Welcome.tsx
│       └── mypage/
│           ├── index.page.tsx
│           └── config/
│               └── index.page.tsx   # 今回開発を進めたいページ
├── next.config.js
├── package.json
├── tsconfig.json
└── ...
next.config.js
module.exports = {
  pageExtensions: ['page.tsx'],
}

相対URLでいうと、以下のようなページがあることになります。

  • /
    • トップページ
    • ファイル: src/pages/index.page.tsx
  • /mypage
    • マイページ
    • ファイル: src/pages/mypage/index.page.tsx
  • /mypage/config
    • 設定ページ(今回開発を進めたいページ)
    • ファイル: src/pages/mypage/config/index.page.tsx

Welcome.tsx はトップページから利用しているコンポーネントであり、拡張子が .page.tsx ではないため、ページとしては存在しません。

この状態で開発サーバーを立ち上げると、 /mypage/config にアクセス可能です。拡張子が .page.tsx であり、ページとしてルーティングに含まれているので、当然の結果です。

まずは拡張子を変更してみる

では、一旦 /mypage/config をルーティングとビルドから外してみましょう。拡張子を .page.tsx から変更すればよいので、簡単です。

ファイル構成
.
├── src/
│   └── pages/
│       ├── index.page.tsx
│       ├── Welcome.tsx
│       └── mypage/
│           ├── index.page.tsx
│           └── config/
│               └── index.page.dev.tsx   # .page.tsx -> .page.dev.tsx に変更
├── next.config.js
├── package.json
├── tsconfig.json
└── ...

このように変更し、/mypage/config にアクセスしてみましょう。404ページが表示されましたね!

pageExtensions を変更する

いっさい表示されないままでは困ります。開発環境ではちゃんと表示されて、本番環境では表示されないようにしたいですよね。pageExtensions の設定を変更していきましょう。

環境変数の定義(開発環境)

開発環境と本番環境で設定を切り替えるため、環境変数を使います。ここでは、 true | false いずれかの値が入る IS_DEVELOPMENT という環境変数を定義します。

Next.js はローカルに置いたファイルから環境変数をロードしてくれるので、開発環境ではこれを利用しましょう。

https://nextjs-ja-translation-docs.vercel.app/docs/basic-features/environment-variables#loading-environment-variables

.env.localファイルを作成します。内容は以下です。

.env.local
IS_DEVELOPMENT=true

pageExtension の設定

そして、IS_DEVELOPMENT によって pageExtensions が設定されるよう、以下のように next.config.js を修正します。

next.config.js
const nextConfig = {
  pageExtensions:  # 変更するプロパティ
    process.env.IS_DEVELOPMENT === 'true'
      ? ['page.tsx', 'page.dev.tsx']
      : ['page.tsx'],
};

環境変数の定義(本番環境)

本番環境においても IS_DEVELOPMENT=false を設定します。CI でビルドしているならそのコンテキストでの環境変数、Vercel や Render などのサービスを利用しているならそのサービスの環境変数で設定します。(厳密にはこれを設定しなくても意図通りに動きますが、私は一貫性のために設定しています)

おわりに

もちろんこれ以外にも方法はありそうですが、いまのところもっともシンプルな解決策だと判断し一旦このやり方を採用しました。もっといい方法をご存知の方がいましたら、ぜひコメントで教えてほしいです!

SocialPLUS Tech Blog

Discussion