Next.js の dev サーバーが HTTPS で立ち上がる仕組み
Next.js 13.5 からは dev サーバーが HTTPS で立ち上がる
Next.js 13.5 からは dev サーバーが HTTPS で立ち上がるようになっています。
next dev --experimental-https
[Feature] HTTPS support for development: next dev --experimental-https
すべての開発内容に HTTPS が必要なわけではありませんが、例えば認証系を試す際に認証プロバイダによっては HTTPS が必須だったりするので、そのような場合に便利です[1]。
ローカル開発環境の HTTPS 化自体は、Next.js 13.5 以前でも実現できました。しかし起動スクリプトとして組み込まれているのを私はみたことがなく、Next.js の仕組みが汎用的に使えるものであれば自分の別のプロジェクトでも npm scripts として応用できるのでは?と思い、調べてみました。
結論
- Next.js の --experimental-https オプションでは、内部的に mkcert を利用して自己証明書を生成している。
- 処理としては mkcert のバイナリをダウンロードして自己証明書を発行し、それをサーバ(Node.js の https モジュール)のオプションとして渡している。
Next.js の --experimental-https オプションの挙動
エントリポイント
Next.js の CLI は next
に続く第一引数をコマンドとして解釈し、指定されたコマンドに応じて動的に実行するモジュールを切り替えています。
next dev
であれば cli/next-dev
を import し、nextDev
を実行しています。
runDevServer
: CLIから開発サーバ起動のブリッジ
cli/next-dev#nextDev
では next dev
で指定されたオプションを解釈し、適当な開発サーバを起動します。最後に実行されるのが runDevServer
です。
この処理の中で --experimental-https
が指定されている場合の分岐が加わります。--experimental-https
には 2 つの挙動があります。
-
--experimental-https-key
と--experimental-https-cert
が指定されている場合は、指定されたキーと証明書を使って HTTPS サーバを起動する。 -
--experimental-https
のみ指定されている場合は、自己証明書を生成して HTTPS サーバを起動する。
1 の挙動について、https 化の機能が実験的であるためにコマンドラインオプションとして実装されていますが、将来的に experimental が外れた場合には環境変数での設定に置き換えられる可能性があります。[2]
実際にサーバが立ち上がる部分を一旦保留し、2 の挙動における自己証明書の生成について確認します。
createCertificate
: 自己証明書の発行
ファイル名からもわかるように、このモジュールは mkcert を使って自己証明書を生成しています。
処理の流れは以下の通りです。
- プラットフォームに応じた mkcert のバイナリを、mkcert の GitHub リポジトリからダウンロード
- mkcert を利用してルート認証局の証明書と秘密鍵を作成
- 実際に発火するコマンド(オプション指定なし):
mkcert -install -key-file 'certificates/localhost-key.pem' -cert-file 'certificates/localhost.pem' localhost 127.0.0.1 ::1 example.com
-
-key-file
オプションでは生成される秘密鍵の保存先ファイルパスを指定します。-cert-file
オプションでは生成される証明書の保存先ファイルパスを指定します。
- 実際に発火するコマンド(オプション指定なし):
- 生成した証明書を .gitignore に追加
- 秘密鍵、証明書、ルート認証局の証明書を値として返却
startServer
: 開発サーバの起動
runDevServer
では子プロセスとして startServer
を実行し、nextWorkerReady
が発火されたタイミングで証明書を含むオプションを渡します。
startServer
では証明書が指定されている場合、 Node.js の https
モジュール[3]を使って HTTPS サーバを起動します。
これによって HTTPS 化された開発サーバーが立ち上がります。
余談: --experimental-https オプションのテスト
こういう類のテストをどうやるんだろう?と思って PR を探していたら、コンソールの出力結果を確認するテストでした。
アサーションとして使用されている check
メソッドは Next.js 内で使用されているテストユーティリティのようです。
おわりに
「利用用途はないけど、Remix 製の個人ブログで試してみるかあ」と思って、Remix のドキュメントをみたら、ここまで確認した内容とほぼ同じことが書いてあることに気がつきました(そしてもういいかと思って https 化をやめました)。
Discussion