跳到正文
Hacker News· olalonde·· 6 天前AI 评分58

Vercel Labs 推出 Portless,用命名 .localhost URL 替代本地端口号

Portless: Vercel Labs Replaces Localhost Ports with Named URLs

AI 导读

Vercel Labs 发布 Portless,用稳定的命名 .localhost URL 替代 localhost:3000 这类端口地址,例如 myapp.localhost 和 api.myapp.localhost。

正文 · AI 翻译

每个开发者心里都有一张端口地图。3000 是前端。3001 是另一个前端。8080 是 API。5432 是 Postgres。6379 是 Redis。而到了某个时候,你开始一个新项目,发现某个东西已经占用了 3000,于是你把它改成 3002,更新三个配置文件,然后纳闷为什么到了 2026 年这还是个问题。

来自 Vercel Labs 的 Portless 用稳定的、具名的 .localhost URL 取代了这一切。localhost:3000 变成 myapp.localhost。API 的 localhost:3001 变成 api.myapp.localhost。端口号消失了。

3.8k 星标。积极维护中。大约 30 秒即可完成设置。


端口的问题

基于端口的本地开发存在一种摩擦,它如此常见,以至于我们已经不再注意到它:

端口冲突 —— 两个项目无法共用同一个端口。你要么杀掉其中一个,要么更改端口,而这会连锁引发各处的配置更改。

Cookie 和存储泄漏 —— 浏览器将 cookie 的作用域限定在 localhost,与端口无关。把你的认证应用跑在 :3000 上,另一个项目跑在 :3001 上,它们就会共享 cookie、localStorage 和 IndexedDB。一个应用的数据渗入另一个应用,导致莫名其妙的测试失败。

没有人类可读的上下文 —— 浏览器历史记录里的 localhost:3000 什么也告诉不了你。那是 Next.js 应用?Vite 项目?还是 Express 服务器?你丢失了上下文。

Monorepo 和 worktree 的痛苦 —— 在 monorepo 中同时运行多个服务意味着要在脑子里维护一张端口登记表。在两个 Git worktree 中运行同一个项目(比较分支时的常见做法)需要更改端口,而更改端口就会更改配置,进而破坏各种东西。

智能体硬编码了错误的端口 —— 像 Claude Code 和 Cursor 这样的编码智能体会从配置文件中读取端口号,并把它们硬编码进测试、脚本和文档中。当端口发生变化时,它们写的一切就都错了。


Portless 如何工作

npm install -g portless

# Instead of: next dev
portless run next dev
# → Your app is now at: myapp.localhost
# → Subdomains: api.myapp.localhost, docs.myapp.localhost

Portless 运行一个本地 DNS 解析器和反向代理。当你通过 portless run 启动一个开发服务器时,它会:

  1. 根据你的项目目录名分配一个具名的 .localhost URL
  2. 将该 URL 路由到开发服务器实际选中的任意端口
  3. 为多服务项目自动管理子域名

端口在底层依然存在 —— Portless 只是让它变得不可见。


具名 URL 修复的不只是冲突

.localhost 命名改变的不只是端口冲突:

浏览器历史记录变得有用了。 myapp.localhost 和 otherap.localhost 是不同的条目。你能分辨出自己当时在做什么。

默认实现 Cookie 隔离。 每个 .localhost 子域名都是独立的源。Cookie、localStorage 和 IndexedDB 的作用域都正确了。不再有莫名其妙的跨项目状态污染。

与队友共享。 “那个在哪个端口上?”从 Slack 里消失了。答案是“它在 projectname.localhost” —— 对团队里的每个人来说都一样。

文档中的稳定 URL。 在 README 里写上 http://myapp.localhost/api/users,它对团队里的每个开发者都有效,无论服务器碰巧选中了哪个端口。


智能体的角度

这是大多数开发者工具文章忽略的部分。编码智能体 —— Claude Code、Cursor、GitHub Copilot Workspace —— 通过读取配置文件、运行命令和发起 HTTP 请求来与本地开发环境交互。端口号对它们来说是一道锋利的边缘。

当智能体搭建一个新服务时,它会读取现有端口,挑一个可用的,然后把它硬编码进测试、环境文件和文档中。当有什么东西改变了那个端口 —— 一次冲突、一次配置更新、队友运行了别的东西 —— 智能体写的一切就都坏了。

使用 Portless 后,agent 写入的是 http://myservice.localhost 而不是 http://localhost:3847。该 URL 是稳定的。它不会随底层端口的变化而改变。agent 的输出保持正确。

Portless 的 README 明确指出了这一点:“For humans and agents.” 这不是事后才想到的。


框架支持

Portless 可与主流开发服务器框架配合使用:

  • Next.js
  • Vite
  • Express
  • Nuxt
  • React Router
  • Angular
  • Expo

portless run 命令可包装任何 npm run dev 等价物。如果你的框架会启动开发服务器,Portless 就能为它提供前端。


设置

npm install -g portless

# Wrap your existing dev command
portless run npm run dev
portless run next dev
portless run vite
portless run node server.js

你的应用会立即获得一个命名 URL。对于多服务项目,子域名会自动可用:

myapp.localhost          → frontend (port 3000)
api.myapp.localhost      → API server (port 8080)  
docs.myapp.localhost     → docs site (port 4000)

无需配置文件。无需 DNS 设置。开箱即用。

仓库:github.com/vercel-labs/portless


为什么这东西早该存在

基于端口的本地开发是那种所有人都容忍的事情,因为其他所有人都在容忍它。没有技术理由说明 localhost:3000 比 myapp.localhost 更好——它只是更老而已。

Portless 是一个小小的生活质量修复,却有着巨大的影响:更快的上手(新开发者不必学习端口映射)、更少的神秘 bug(cookie 隔离),以及更可靠的 agent 输出(稳定的 URL,而不是会漂移的端口号)。

短时间内获得 3.8k 星标,说明开发者社区也认同这一点。如果你在运行多个本地项目——尤其是在 monorepo 中或使用 AI 编码工具时——它值得花 30 秒安装。

来源:Hacker News · themenonlab.blog