ツールは 2 つ、問題は 1 つ:開発サーバーが HTTPS で到達可能である必要があります。mkcert はローカルで信頼される TLS 証明書を与え、https://localhost:3000 がそのまま動きます。トンネルは本物の CA の本物の証明書に裏打ちされた公開 HTTPS URL を与えます。両者は競合相手ではなく——別の問題を解きます——が、人々はずっと競合のように扱います。
短い答え
- 自分のマシンの、自分のブラウザーだけに HTTPS が要る? mkcert を使う。
- 外部サービス(Stripe、GitHub、Auth0、スマホ)が開発サーバーに到達する必要がある? トンネルを使う。
- 両方? 両方動かす。ぶつかりません。
これが記事の全部、3 つの箇条書きです。残りは理由だけ。
mkcert:30 秒でローカル信頼の証明書
mkcert は OS の信頼ストアにローカル認証局をインストールし、そこから証明書を発行します。CA が信頼されているので、ブラウザーは証明書を信頼済みと見ます。この接続ではプライバシーが保護されませんの警告も、--ignore-certificate-errors フラグも、自作の自己署名証明書もなし。
# マシンごとに 1 回
mkcert -install
# プロジェクトごとに 1 回
mkcert localhost 127.0.0.1
# これで localhost.pem と localhost-key.pem ができる
開発サーバー(Vite、Next.js、Express、Django runserver_plus はすべて TLS 引数をサポート)に組み込めば、本物の証明書で https://localhost:3000 が手に入ります。
落とし穴:その CA を信頼するのはあなたのマシンだけ。同僚のブラウザーは警告します。スマホは CA ルートを手動でインストールしない限り信頼しません。
トンネル:本物の HTTPS、本物の公開 URL
localhost トンネルは公開 HTTPS URL からローカルポートへトラフィックを転送します。証明書は本物の CA(Let's Encrypt など)が発行し、あらゆるデバイスのあらゆるブラウザーが信頼します。
npx portpreview 3000
トンネルはクラウドゲートウェイで TLS 終端を処理します。ローカルサーバーは素の HTTP のままで構いません——公開 URL が HTTPS で、外部サービスが触れる面はそこです。
並べて比較
| ニーズ | mkcert | トンネル |
|---|---|---|
| ローカルブラウザーでの HTTPS | はい | はい(公開 URL 経由) |
| ブラウザーでの service worker / secure cookie テスト | はい | はい |
| 外部プロバイダーが到達できる | いいえ | はい |
| 手元のスマホが到達できる | いいえ(CA を入れなければ) | はい |
| OAuth プロバイダーが URL を受け入れる | 時々(Google:はい、多くは:いいえ) | はい |
| Stripe / GitHub / Twilio が Webhook できる | いいえ | はい |
| セットアップ時間 | マシンごと 30 秒 | セッションごと 1 コマンド |
| オフラインで動く | はい | いいえ |
| 機内モードでも生きる | はい | いいえ |
みんなが間違えるところ
Webhook テストに mkcert を使おうとする
Stripe はあなたのマシンのローカル CA を信頼できません。ブラウザーで証明書がどれだけ信頼済みに見えても——Stripe は別ネットワークにいます。公開インターネットからの受信トラフィックにはトンネルが必要です。
1 人ブラウザーだけの HTTPS にトンネルを使う
自分のブラウザーで service worker を動かしたい、secure cookie を設定したいだけなら、mkcert のほうが速くオフラインでも動きます。証明書ファイルで済むことにトンネルセッションを浪費しないこと。
1 つのツールを選んでもう片方のユースケースを無理に通す
両方動かすので大丈夫。私たちのセットアップの大半は、日々のブラウザー側作業に mkcert、Webhook や OAuth コールバックのテスト時にトンネルを使います。package.json で衝突なく同居します。
Caddy や nginx は?
はい、開発サーバーの前に自動 HTTPS の Caddy を置けますし、それも動きます——本質的に「余計な手順とリバースプロキシつきの mkcert」です。多くのローカル開発では mkcert のほうが簡単。複数のローカルサービスを伴う凝ったルーティングには Caddy が活きます。
私たちの実際のセットアップ
私たちが作業するあるリポジトリでは、localhost 側 HTTPS 用に dev スクリプトに mkcert、誰かが Webhook やモバイルテストを要るときに portpreview を走らせる別の tunnel npm スクリプトがあります。トンネル URL は env 変数で渡され、OAuth リダイレクト URI を簡単に差し替えられます。配線に 20 分、それ以降ローカル TLS を考えたことはありません。
OAuth 向けのトンネル設定は OAuth コールバックをローカルでテストする方法を参照。同僚やデザイナーとプレビューを共有するなら ローカル開発サーバーの共有。このセットアップのトンネル側は PortPreview のウェイトリストへ。