Vite 项目启动后,终端里冒出一行黄字Network: use --host to expose,紧接着 Local 地址能正常打开,但换成http://192.168.x.x:5173去访问,就是一直转圈、连接超时。这个场景我在社区里见过无数次,自己也踩过。先说结论:这不是 Vite 出 bug,也不是你的项目配置炸了,纯粹是 Vite 的默认行为——开发服务器默认只监听本机回环地址,外部网络的 IP 它根本不理。这篇文章我会从网络监听的角度把原因讲透,再给出命令行、配置文件、脚本三种解决方案,最后附上我实际排查过的各种坑,包括防火墙、多网卡、HMR 失效这些场景。
1. 先把那行提示和背后的网络模型讲清楚
1.1 “use --host to expose”不是报错,是提醒
第一次看到这行字的人很容易慌,因为它长得像报错:黄颜色、粗体,出现在 Local 地址下方。实际上 Vite 只是很贴心地告诉你,当前开发服务器只绑定了 localhost,如果你想让手机、虚拟机、同事的电脑通过局域网 IP 来访问,需要主动加一个--host参数。
Vite 3 之后,这个提示成了标准输出的一部分。原因是 Vite 默认的server.host是'localhost',也就是说监听范围仅限于回环接口。回环接口是什么?你可以把电脑的网络通信想象成一栋楼的门禁:localhost 相当于只有本楼住户能走的小门,0.0.0.0才相当于朝马路开的大门。默认情况下 Vite 只开了小门,本机浏览器访问没问题,但外部设备想进来,连门都找不到。
这个提示不会影响本地开发,所以很多人第一次看到它选择无视。可一旦遇到“给别人演示页面”“手机真机调试”“后端同事要看前端效果”这些场景,问题马上冒出来。与其等到联调时手忙脚乱,不如先把这行字理解透。
1.2 localhost、127.0.0.1、0.0.0.0 到底差在哪
这里有必要把三个最常见的地址理清楚,很多人就是混在这里。
127.0.0.1:这是一个固定的回环地址。发往它的数据包只会回到本机,绝不会出现在真实网卡上,访问它相当于对着自己说话。localhost:这是一个主机名,不是一个 IP。系统通常把它解析到127.0.0.1,有些系统还会解析到::1(IPv6 回环地址)。Vite 默认绑定的就是它。0.0.0.0:这是一个通配监听地址。它表示“监听本机所有网络接口上的对应端口”。当你把服务绑到0.0.0.0:5173时,无论是回环地址、有线网卡的 IP、无线网卡的 IP,还是虚拟网卡的 IP,只要数据包是发给本机 5173 端口的,都能被服务收到。
用大白话说:localhost 是只给自己用,0.0.0.0 是通通都接。Vite 默认选了前者,所以你在终端里只看到 Network 的提示,却看不到一个实际可用的 Network 地址。理解这一点,后面所有解决方案就把住了命门——你要做的,就是让 Vite 从“只监听自己”切换成“监听所有网卡”。
1.3 Vite 为什么不默认开放外部访问
很多人会问:直接默认绑 0.0.0.0 不就好了?省得每次都要加参数。Vite 团队这么做是有意为之,核心是安全考虑。
开发服务器本质上是一台“不设防”的机器:它没有鉴权、没有访问控制、代码变更会实时编译,甚至允许通过 WebSocket 做热更新。如果随意暴露在公网或者一个不可信的局域网里,别人可以通过你开的端口读取页面源码、干扰你的开发环境,甚至利用某些框架的调试接口做进一步操作。默认绑 localhost,就等于默认把门锁好,想要对外开放必须显式表明意向。
想明白这一点,你再去看--host参数,就会发现它不只是一个“打开网络访问”的开关,更像是一个“我确认要暴露在网络上”的表态。理解了设计意图,遇到类似的问题就不会再觉得 Vite 在为难你了。
2. 三种让 Vite 对外可访问的做法
2.1 最快方式:命令行直接加 --host
最直接的改法,启动命令变成:
vite --host注意,--host后面可以不带值。不带值时等价于--host true,Vite 会把它解析成监听0.0.0.0,也就是所有网卡。执行之后,你会发现终端输出多出了几行Network:开头的地址,比如:
Local: http://localhost:5173/ Network: http://192.168.1.100:5173/这个http://192.168.1.100:5173/就是给局域网内其他设备用的地址。如果你嫌自动选网卡不靠谱,也可以手动指定:
vite --host 192.168.1.100这样 Vite 只绑定这一个 IP,其他网卡的请求全部忽略。还有一种写法是vite --host 0.0.0.0,效果和vite --host一样,只是把话说得更明白。
实测下来,这个方式最适合临时场景:比如今天就为了让手机看个样式效果,启动时加个参数,调试完一关,项目配置一点没动,干净利落。
2.2 工程化方式:写进 vite.config.js
命令行参数只对当前这次启动有效,下次启动又得重新敲。如果你的场景是长期需要在局域网里联调,或者团队里每个人都有同样需求,更合适的做法是把配置写死在项目里:
// vite.config.js import { defineConfig } from 'vite' export default defineConfig({ server: { host: true, // 监听所有地址,等价于 0.0.0.0 }, })host的取值有几个可选:true、'0.0.0.0'、'localhost'、或者一个具体的 IP 和主机名。其中true和'0.0.0.0'等价;想绑特定网卡就写成host: '192.168.1.100'。
这里我建议:项目仓库里要不要提交这个配置,得看团队约定。因为host: true之后任何人npm run dev都会把服务暴露到局域网,如果公司网络环境比较复杂,还是有一点风险。更稳妥的做法是提交host: 'localhost',开发时按需用命令行覆盖。配置写死不等于必须写死成对外开放,得在便利和安全之间找平衡。
2.3 npm scripts 里的参数透传细节
大多数项目的启动命令是npm run dev,而 scripts 里写的是"dev": "vite"。这时候直接敲npm run dev --host是没用的,因为参数会传给 npm 而不是 vite。正确写法是:
npm run dev -- --host多出来的--是 npm 的参数分隔符,它告诉 npm:后面的内容原样传给被执行的命令。除了这种临时写法,也可以在 package.json 里直接改脚本:
{ "scripts": { "dev": "vite --host", "dev:local": "vite" } }我个人的习惯是保留默认 dev 脚本不动,需要暴露网络时用npm run dev -- --host。少一个全局改动,就少一份“忘记关暴露”的担心。团队协作时还可以约定 dev 默认带--host,但前提是大家都能意识到服务是开放的。
3. 改完之后怎么验证、怎么跨设备访问
3.1 确认监听地址的三种手段
改完配置后,不要急着拿手机去试,先在本机确认服务到底监听在哪。常见手段有三种。
第一,看终端输出。如果出现了Network: http://192.168.x.x:5173/,说明已经绑定成功。第二,用系统命令查看端口监听状态。Windows 上执行netstat -ano | findstr :5173,你会看到监听地址一栏是0.0.0.0:5173或[::]:5173,这就代表所有网卡都在收。如果看到127.0.0.1:5173,说明还是没改成功。macOS/Linux 可以用lsof -i :5173或者ss -tlnp | grep 5173,效果类似。第三,直接访问测试。本机打开http://127.0.0.1:5173能开还不够,再用局域网 IP 访问一次,后者能开才说明服务真的对接到了真实网卡。
这里有个很容易被忽略的判断标准:本机能访问http://localhost:5173并不能说明什么,因为 localhost 走的是回环,和局域网访问是两条完全不同的路径。真正有效的验证,一定是通过局域网 IP 访问也成功。
3.2 局域网内其他设备的访问方式
服务监听打通后,手机或者别的电脑怎么访问?很简单,保证两台设备在同一个局域网段,比如都连着同一个路由器,然后在目标设备的浏览器里输入http://192.168.1.100:5173。
如果你手机和电脑连的不是同一个网,或者路由器开了 AP 隔离(很多路由器会把访客网络和主网络隔开,互不相通),那就会一直超时。排查这类问题,可以先用手机浏览器访问路由器管理页或者做一个 ping 测试,确认手机到电脑的 IP 层是通的,再回头怀疑 Vite。网络层的连通性永远是链路里的第一关,这层不通,应用层配置再对也没用。
多设备同屏调试的场景下,还有个实用技巧:一台电脑、多台设备同时访问同一个地址,Vite 会分别为每个浏览器建立对应的 WebSocket 连接,热更新可以各自独立工作,不需要额外配置。这个能力在做多端兼容测试时特别好用。
3.3 网络环境下 HMR 更新失效怎么办
这是局域网联调里最诡异的问题:页面能打开,终端也显示更新了,但手机上的页面就是不刷新。十有八九是 HMR 的 WebSocket 连接出了问题。
Vite 的 HMR 依赖 WebSocket,浏览器端脚本默认会尝试连接当前页面所在的 host。也就是说,你通过http://192.168.1.100:5173打开页面,WebSocket 就会连ws://192.168.1.100:5173,大多数情况下没问题。但在某些网络拓扑里,比如请求经过了转发、电脑有多个网卡、或者 DNS 解析异常,WebSocket 可能连到了错误的地方,更新消息就发不过来。
遇到这种情况,可以给server.hmr显式指定地址:
server: { host: true, hmr: { host: '192.168.1.100', port: 5173, }, }把 host 写死成实际访问的 IP,HMR 消息就能稳定送达。不过要注意,写死 IP 会让 IP 变化的场景失效,所以更推荐只在需要时临时加上,联调完再删掉。
4. 网络 IP 访问失败的高频原因与排查
4.1 Windows 防火墙把 node.exe 拦在门外
本机一切正常,手机访问就超时,这个现象八成是防火墙干的。Windows 防火墙在 Node.js 第一次监听端口时,通常会弹一个“是否允许此应用通过防火墙”的窗口,很多人手一滑点了取消,或者某些企业镜像默认把入站连接全挡了,于是 node.exe 只能被本机访问,局域网请求在系统网络层就被掐死了。
排查方法:打开 Windows Defender 防火墙的高级设置,看是否有针对 Node.js 的“允许入站连接”规则。如果没有,最简单的做法是删掉旧的拦截规则,然后重新启动一个监听端口的 Node 服务,触发系统弹窗,再勾选“专用网络”允许。
命令行方式也可以,在管理员 PowerShell 里执行:
netsh advfirewall firewall add rule name="Vite Dev" dir=in action=allow protocol=TCP localport=5173这条命令只为 5173 端口放行入站连接。注意这是给当前网络配置文件加规则,如果电脑连着多个网络环境,改完记得确认规则的作用域是“专用”还是“公用”。公司网络和公共网络的默认分类可能不一样,规则加错作用域,换个网络环境就又不通了。
4.2 多网卡环境下访问了错误的 IP
我踩过最冤的一次坑:Vite 明明已经绑了 0.0.0.0,终端也打出了 Network 地址,但手机就是打不开。后来一查,终端打印的是 VMware 虚拟网卡的地址,而电脑真正连家庭路由器的是另一块无线网卡,网段完全不一样,手机当然访问不到。
当机器上装了 VMware、VirtualBox、Docker 这类软件时,vite --host会打印出多个 Network 地址,其中有真实局域网地址,也有虚拟网卡地址。解决办法是:用ipconfig查看当前有效的 IPv4 地址,找到和路由器同网段的那一个;然后手动指定vite --host 192.168.1.100,避免绑到虚拟网卡上。如果经常在不同网络环境切换,可以写一个小脚本,动态获取当前主要网卡 IP 再拼启动命令,省得每次手动复制。
这一步的教训是:终端不会骗你,但终端也不知道你到底想让哪块网卡对外。多网卡机器上,明确指定监听地址往往比0.0.0.0更省心。
4.3 端口被占与 strictPort 的选择
另一个常见现象是,Vite 默认端口 5173 被其他程序占了,于是自动跳到 5174、5175……终端上其实写得很清楚,但很多人在手机里还输 5173,自然打不开。
Vite 的行为是端口被占用时自动往后顺延,不会直接崩。如果你希望它报错而不是静默换端口,可以在配置里打开 strictPort:
server: { host: true, strictPort: true, }这个开关的意义在于:端口必须是你指定的那个,否则直接退出并报错。尤其是在做固定联调地址、或者地址已经写进别人书签时,静默换端口反而会造成更大混乱,不如出错得快一点。如果只是临时想换个端口,直接用命令行--port即可,比如vite --host --port 8080。
顺带一提,排查端口问题时,终端输出永远是最快的信息源。启动后扫一眼有没有类似Port 5173 is in use, trying another one...的日志,能省下不少猜谜时间。
4.4 WSL2/容器等特殊环境的网络差异
在 Windows 上用 WSL2 跑 Vite,是本类问题的高发区。WSL2 运行在一个轻量虚拟机的网络里,有自己的虚拟网卡 IP。Windows 侧对 localhost 做了自动转发,所以你在 Windows 浏览器打开 localhost:5173 通常没问题,但局域网里的其他设备访问 Windows 主机 IP 时,流量不会自动转发到 WSL2 内部。这就是“本机明明能开,别人死活连不上”的典型局。
碰到这种环境,常见的处理思路有几种:把 Vite 的 host 设为 WSL2 实例自身的 IP,再从 Windows 上用 netsh 做端口转发;或者干脆不在 WSL2 里跑 Node,改用 Windows 原生环境运行 Vite,绕开虚拟网卡那层转发;在 Docker 容器里跑 Vite 也类似,需要把容器端口映射到宿主机 0.0.0.0 上。
这类问题的本质都一样:服务监听的“空间”和外部设备能访问到的“空间”不是同一个。光在应用层加--host是不够的,网络层的转发也得打通。遇到这种环境类问题,先跳出来画一下数据包的路径,比闷头改配置有效得多。
5. 再往深走一步:host 配置的几个进阶点
5.1 server.host 的取值对照与安全提醒
把 host 的各种取值整理成一张表,方便查阅:
| 取值 | 监听范围 | 典型场景 |
|---|---|---|
'localhost' | 仅回环接口 | 默认值,纯本机开发 |
true或'0.0.0.0' | 所有网卡接口 | 局域网联调、手机预览 |
'192.168.1.100' | 指定网卡 | 多网卡机器、虚拟网络环境 |
| 自定义主机名 | 解析后的地址 | 配合本地域名使用 |
安全提醒必须说:绑 0.0.0.0 之后,只要和你在同一个二层网络的设备,都能访问到你的开发服务。开发服务器没有生产环境那些防护,可能在浏览器控制台输出源码映射、调试信息,也可能因为某些依赖暴露管理接口。所以我在公司网络里,宁可临时加--host用完就关,也不太愿意长期把它写死在配置文件里。
5.2 指定网卡绑定和 HTTPS 场景
如果你不想用 0.0.0.0 一把梭,Vite 也支持绑指定网卡。先看机器上有哪些 IP,Windows 用ipconfig,macOS/Linux 用ip addr或ifconfig,挑出真实局域网网段那个,然后:
vite --host 192.168.1.100效果就是终端只打出这一个 Network 地址,其他网卡不会收到请求。好处是减少误用虚拟网卡 IP 导致的无谓排查,坏处是 IP 会变,换个网络就要重新改。适合“临时确认”而不是写死到配置里。
HTTPS 场景是另一个常见需求,比如调用一些只允许 HTTPS 的浏览器 API,或者手机端调试时证书受限。可以在server.https里配置本地证书,再配合host: true使用。但 HTTPS 还牵扯到浏览器信任证书的问题,证书链不完整的话,即使 IP 能访问,页面也会报不安全,比 HTTP 模式多一道关。真到这一步,建议先用工具生成自签名证书,再在目标设备上手动安装信任,链路会比 HTTP 长不少。
5.3 allowedHosts:访问域名被拦截时的解法
Vite 较新的版本里,还有一个和 host 相关的坑:当外部设备用一个自定义域名或者转发域名来访问你的开发服务器时,页面可能直接显示类似Blocked request. This host (...) is not allowed的提示。
这是因为开发服务器会校验请求头里的 Host 字段。正常情况下,你的项目本地访问是 localhost,局域网访问是 IP,都在许可范围内。但如果你通过某种自定义域名访问,Vite 不认识这个域名,出于防止 DNS 重绑定的安全考虑,就会拒绝响应。
解决方式是在配置里声明允许的域名:
server: { host: true, allowedHosts: ['my-app.example.com'], }想省事也可以写成allowedHosts: true,意思是开发模式下接受任何 Host 头,但这样等于把这个安全校验关掉了。我的建议是:能列具体域名就列具体域名,别图省事全局放开。
6. 问题速查表 + 我的实操习惯
6.1 常见问题速查表
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| 终端没有 Network 地址 | 没加 --host | vite --host或server.host: true |
| 有 Network 地址但手机打不开 | 防火墙拦截 | 给 node 或对应端口加放行规则 |
| 打出的 Network IP 不是真实局域网 IP | 多网卡绑到了虚拟网卡 | 手动指定vite --host具体 IP |
| 本机 localhost 能开,局域网 IP 不能 | 服务仍绑在 localhost | 用 netstat/lsof 确认监听地址 |
| 页面能打开但 HMR 不生效 | WebSocket 连错地址 | 配置server.hmr.host为访问 IP |
| 手机访问提示连接超时 | 不在同一网段或 AP 隔离 | 确认设备在同一局域网再尝试 |
| 自定义域名访问被拦截 | Host 头不在白名单 | 配置server.allowedHosts |
| WSL2/Docker 里跑 Vite 外部访问不了 | 网络层未打通 | 做端口映射或换运行环境 |
6.2 我个人的几个实操习惯
最后分享一点自己的经验。第一,凡是涉及给别人访问的开发服务,启动后我第一件事就是盯着终端看,确认 Network 地址打印出来再往下走;没有地址就先别折腾其他环节。第二,排查顺序永远是:服务监听状态 → 本机 IP 访问 → 防火墙放行 → 手机访问,反过来查会浪费大量时间。第三,暴露和安全是个平衡点,我一般只在明确需要联调的时段加--host,联调完就切回默认,不为一时方便留隐患。
Vite 的 host 问题本质上就是个网络监听问题,把 localhost 和 0.0.0.0 的区别理解透之后,再碰到“开发服务器别人访问不了”,你大概只需要花两分钟检查监听、防火墙、网卡这几关就够了。真遇到一次性解决不了的环境问题,记得按数据包路径一步步画着查,比焦虑地来回试参数有用得多。