所有文章
HTTPSmkcertlocal developmentlocalhost tunneling

localhost 上的 HTTPS:mkcert 与隧道,诚实对比

两个工具,一个问题:你的开发服务器需要通过 HTTPS 可达。mkcert 给你一个本地受信的 TLS 证书,让 https://localhost:3000 直接能用。隧道给你一个由真实 CA 颁发的真实证书支撑的公网 HTTPS URL。它们不是竞争对手——解决不同的问题——但人们总把它们当成竞争对手。

简短答案

  • 只需要在自己机器、自己浏览器里用 HTTPS?用 mkcert。
  • 需要外部服务(Stripe、GitHub、Auth0、一部手机)能到达你的开发服务器?用隧道。
  • 都要?都跑。它们不冲突。

三个要点就是整篇文章。其余只是为什么。

mkcert:30 秒内本地受信证书

mkcert 把一个本地证书颁发机构装进你操作系统的信任库,并从中签发证书。浏览器视该证书为受信,因为 CA 受信。没有你的连接不是私密连接的警告,没有 --ignore-certificate-errors 标志,不用自己折腾自签证书。

# 每台机器一次
mkcert -install

# 每个项目一次
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 / 安全 cookie 测试
外部提供商能到达你
手里的手机能到达你否(除非装 CA)
OAuth 提供商接受该 URL有时(Google:是;很多:否)
Stripe / GitHub / Twilio 能向它发 webhook
配置时间每台机器 30 秒每会话一条命令
离线可用
飞行模式下可用

人们的常见误区

试图用 mkcert 做 webhook 测试

Stripe 无法信任你机器的本地 CA。无论证书在你浏览器里看起来多受信——Stripe 在另一个网络。任何来自公网的入站流量都需要隧道。

为单人纯浏览器的 HTTPS 用隧道

如果你只想让 service worker 工作,或在自己浏览器里设置一个安全 cookie,mkcert 更快且离线可用。别为一个证书文件就能解决的事烧掉一个隧道会话。

选定一个工具并硬把另一个用例塞进去

两个都跑没问题。我们大部分设置用 mkcert 做日常浏览器端工作,测试 webhook 或 OAuth 回调时用隧道。它们在 package.json 里无冲突共存。

那 Caddy 或 nginx 呢?

是的,你可以在开发服务器前跑带自动 HTTPS 的 Caddy,这也行——本质上是“多几步加一个反向代理的 mkcert”。对大多数本地开发,mkcert 更简单。对涉及多个本地服务的更复杂路由,Caddy 物有所值。

我们的真实设置

我们工作的一个仓库在 dev 脚本里有 mkcert 用于 localhost 端 HTTPS,还有一个单独的 tunnel npm 脚本,当有人需要 webhook 或移动端测试时运行 portpreview。隧道 URL 通过环境变量传入,所以 OAuth 重定向 URI 很容易替换。接好花了 20 分钟,此后我们再没想过本地 TLS。

关于 OAuth 专用的隧道设置,见如何在本地测试 OAuth 回调。关于与队友或设计师分享预览,分享你的本地开发服务器加入 PortPreview 等候名单,获得这套设置的隧道一侧。

常见问题

本地 HTTPS 我该用 mkcert 还是隧道?
都用,各司其职。mkcert 给你自己的浏览器一个 localhost 上受信的证书,且离线可用。隧道给你一个外部服务和其他设备可达的公网 HTTPS URL。它们不冲突——多数团队两个都用。
mkcert 能处理来自 Stripe 或 GitHub 的 webhook 测试吗?
不能。mkcert 证书只在安装了 CA 的那台机器上受信。无论证书在你本地浏览器里多受信,外部 webhook 提供商都无法到达 localhost。任何入站公网流量都用隧道。
mkcert 适用于 OAuth 的 localhost 回调吗?
一些提供商(Google、Auth0 的某些开发层级)在开发中接受 HTTP 或 HTTPS 的 localhost。很多不接受。mkcert 为接受的那些提供 HTTPS;对严格的,需要带公网 HTTPS URL 的隧道。