把 Vite 开发服务器穿隧道用起来很顺——除了两件第一次会绊住你的事。页面加载了但 HMR 不工作。或者页面根本加载不出来,因为 Vite 拒绝了你的隧道主机名。一旦知道往哪看,两者都是一行配置就能解决。
问题 1:“Blocked request. This host is not allowed.”
Vite 5+ 默认加入了主机检查保护。如果你打开隧道 URL 看到 Blocked request. This host is not allowed,那就是这个检查在拒绝你的 *.portpreview.dev 主机名。
在 vite.config.ts 中修复:
export default defineConfig({
server: {
host: true, // listen on 0.0.0.0
allowedHosts: ['.portpreview.dev'], // accept any subdomain
},
});
开头的点使它成为后缀匹配。如果你想更严格,可以在那里填你具体的隧道主机名,但日常开发用后缀更方便——隧道会话 URL 会轮换。
问题 2:HMR 加载后悄悄断了
HMR 跑在 WebSocket 上。当 Vite 在 localhost:5173 提供服务,而你的浏览器从 https://abc123.portpreview.dev 加载时,HMR 客户端会尝试连接服务器告诉它的那个 URL——也就是本地那个。隧道不转发它,于是 WebSocket 失败,HMR 悄悄停止。
修复 HMR 配置:
export default defineConfig({
server: {
host: true,
allowedHosts: ['.portpreview.dev'],
hmr: {
clientPort: 443, // browser connects on 443 (HTTPS)
protocol: 'wss', // secure WebSocket through the tunnel
},
},
});
现在 HMR 客户端连接到 wss://abc123.portpreview.dev(443 端口),隧道转发升级请求,编辑就如预期般传播。如果你只需要静态重载、不在意通过隧道的 HMR,可以跳过这一步——但你会频繁按 cmd-R。
为什么要给 Vite 穿隧道
三个真实理由:
- 移动测试。在手机上打开 URL,看到带 HMR 的同一个 build。比共享屏幕或逐设备模拟器更好。完整模式参见 用隧道做移动测试。
- 分享进行中的工作。把链接发给设计师或 PM,他们就能实时看到你的分支。无需部署步骤。
- 需要 HTTPS 的 OAuth 和 Webhook 流程。由 Vite 提供的前端要与 Stripe(仅 redirect)、Auth0 等对接。mkcert vs 隧道 讲了如何选择。
SvelteKit、Astro、SolidStart 都用 Vite
上面的配置适用于任何把 Vite 作为开发服务器的框架。SvelteKit 的 vite.config.js 形状相同。Astro 有自己的 astro.config.mjs,里面有一个 vite 子对象——把相同的 server 选项放到那里。SolidStart、Nuxt 3(经由 Vite)和 Qwik City:同一模式。
生产构建是另一回事
以上都是开发服务器的配置。当你运行 vite preview 或提供已构建的 bundle 时,这些都无关紧要,因为没有 HMR,也没有主机检查中间件。此时隧道只是在转发静态文件。
一些小事
- 严格主机 CORS。如果你的前端访问另一个源上的 API(不同的 localhost 端口,或单独的 API 隧道),请在 API 侧设置 CORS。除非你通过
server.proxy指示,Vite 默认不做代理。 - WebSocket 密集的应用。Vite HMR 是一个 WebSocket。如果你的应用为游戏状态、聊天或实时数据使用了另一个 WebSocket,那个是独立的,也需要在你的客户端代码中配置为使用隧道 URL。
- env 文件里的隧道 URL。当前端需要知道自己的公网地址时,我们把当前隧道 URL 作为
VITE_PUBLIC_URL放进.env.local。import.meta.env.VITE_PUBLIC_URL在客户端读取它。
分步操作
- 把
server.host、allowedHosts和hmr块加到你的 Vite 配置中。 - 重启开发服务器。
- 运行
npx portpreview 5173(或 Vite 使用的端口)。 - 在浏览器或手机上打开 HTTPS URL。
- 编辑一个组件。确认 HMR 在不整页刷新的情况下更新页面。
如果 HMR 没更新,打开浏览器控制台——Vite 会记录 WebSocket 连接尝试,你能看到它尝试的 URL。这能告诉你 hmr.clientPort/protocol 的改动是否生效。
加入 PortPreview 等候名单,获得默认保留 WebSocket 升级的隧道。