00:00:00这是 Portless,一款由 Versel Labs 团队推出的命令行工具,
00:00:05他们还开发过 Agent Browser、JSON Render 和 Skills。它用固定的域名取代了本地端口号,
00:00:10让用户和 AI 智能体能轻松访问正确的位置,并防止端口冲突。
00:00:15但它的底层原理究竟是什么?会搞乱我的系统吗?
00:00:20点击订阅,让我们一探究竟。
00:00:21让我们通过一个简单的例子来看看如何使用 Portless。
00:00:26目前我有一个项目运行在 3001 端口上。
00:00:30如果这个项目在后台运行,而我完全忘了这回事,
00:00:33这时我想运行另一个使用相同端口的项目,
00:00:37就会收到“地址已被占用”的报错。
00:00:40这正是 Portless 旨在解决的问题。
00:00:44想象一下,如果你在不同的标签页中为不同项目运行了多个智能体,
00:00:48而它们遇到了这个问题。
00:00:50虽然它们可以自行修复,但如果总有一个可用的端口
00:00:55供它们运行,从一开始就避免冲突,那就更好了。
00:00:58现在,在安装了 Portless 并运行了 Portless 代理的情况下,
00:01:01我可以运行命令 portless,后面跟着我的主机名(这里是 xdlapi),
00:01:06当然,你可以随意命名。
00:01:08接着输入你想运行的命令,也就是 bun run devapi。
00:01:12按下回车后,它会在 4000 范围内找到一个随机的空闲端口。
00:01:16因为这个范围不太可能被其他程序占用。
00:01:20然后它通过 .localhost 1355 上的主机名展示我的应用。
00:01:25默认端口是 1355,代表“less”,因为它是 Portless。懂了吗?
00:01:30点击这里,你可以看到应用已经正常运行了。
00:01:34如果我到另一个应用里做同样的操作,
00:01:37现在它找到了另一个空闲端口,并使用了对应的主机名。
00:01:40但结尾的这个端口号会保持不变。
00:01:42事实上,如果愿意,我们还可以更改它。
00:01:44如果我们将其改为 80 端口,甚至可以完全省略冒号和端口号。
00:01:49所以,如果我在 80 端口启动 Portless 代理(记得使用 sudo),
00:01:53并且同样使用 sudo 启动 Portless 进程,
00:01:55那么我们就可以直接通过“子域名.localhost”来访问。
00:01:59不仅如此,在使用 80 端口的基础上,我们甚至能获得 HTTPS 支持,
00:02:03只需使用 HTTPS 标记,就能启用加密连接。
00:02:08但如果你使用 Vite,就必须在 port 键中设置端口变量,
00:02:13并将 hosts 设置为对应的值。
00:02:15我稍后会在视频中解释原因。
00:02:17Portless 还有很多其他选项,
00:02:21比如可以在前台运行代理以便调试,
00:02:25也可以在没有代理的情况下运行命令,用于调试或作为备选方案。
00:02:30但为什么它每次都使用随机端口号呢?
00:02:33又为什么需要代理呢?
00:02:35让我们深入了解它的工作原理。
00:02:36我们将演示两个流程。
00:02:39一是当你在终端运行 Portless 主命令时会发生什么;
00:02:42二是当浏览器访问 Portless URL 时会发生什么。
00:02:46在这里,当你运行 Portless 命令时(本例中为
00:02:49Portless myapp 配合 barn start 命令),
00:02:52首先会提取主机名和待执行的命令。
00:02:56接下来,它会检查代理是否正在运行。
00:02:59如果没有,它将启动代理。
00:03:01但有一点需要注意,因为你可以自定义代理运行的端口。
00:03:06默认是 1355。
00:03:08但如果你设置的端口号低于 1024,
00:03:12它在运行前会请求你的确认。
00:03:15如果高于该数值,它就会自动运行。
00:03:19接着,它会在 4000 到 4999 之间找一个空闲端口。
00:03:25采用随机端口是为了加快查找过程。
00:03:29因为如果是顺序查找,它必须逐个检查所有端口,
00:03:33如果你运行的进程很多,这可能会花很长时间。
00:03:35找到端口后,它会将详细信息添加到一个 root store JSON 文件中。
00:03:40然后它在该端口上运行你的命令,并将该端口添加到环境变量中,
00:03:47大多数 JavaScript 应用都可以访问这个变量。
00:03:50现在让我们关注这一部分。
00:03:52当浏览器访问一个 Portless URL 时(这里以 myapp 为例),
00:03:56如果我们使用默认端口,那就是 1355。
00:04:00接着,它会完成 DNS 解析,并与代理建立 TCP 连接,
00:04:06代理会提取主机名(即 myapp),
00:04:09然后据此在 root JSON 文件中查找你应用的实际端口。
00:04:15获取正确的端口号后,它会将请求转发到你的实际应用,
00:04:21应用将响应发回给代理,最后再传给浏览器,
00:04:26因为浏览器期待的是来自 1355 端口的响应,
00:04:30而不是代理在此流程阶段随机分配的那个端口。
00:04:35这一套流程对 WebSockets 也同样有效。
00:04:38对于一个周末练手项目来说,这非常令人惊艳。
00:04:40不过,如果你在 Vite 等非 Next.js 项目中使用 Portless,可能会遇到一些问题。
00:04:47首先,因为它使用的是分配给端口变量的随机端口,
00:04:52而不是硬编码的数字,你必须确保你的应用能从该端口运行,
00:04:56这样代理才知道该把流量重定向到哪里。
00:05:00对于 Vite 或类似的构建工具,你可能需要添加 host 键并设置该值,
00:05:06因为它会拒绝来自未知源的请求,而此设置可以禁用该检查。
00:05:10我尝试过使用不同的 allowed host 键值,但似乎不起作用。
00:05:16虽然这个方案看起来有点激进,
00:05:19但如果你只是在本地运行,真的没什么好担心的。
00:05:22和 Vercel Labs 的其他项目一样,Portless 会持续更新,
00:05:26这意味着大部分此类问题在未来都会得到解决,
00:05:30包括对 Windows 的支持等。
00:05:32说到 Vercel Labs,如果你还没试过 Agent Browser,
00:05:36它是让你的智能体与浏览器交互的最佳方式,
00:05:39你可以在下一段视频中了解它的全部信息。