用 servd 替换 http-server

阅读约 6 分钟 qingyu31
migrationhttp-serverstatic

多年来,http-server 一直是 Node 生态里默认的「托管这个目录」工具。servd 力图覆盖它的常见用法,同时移除 Node 运行时依赖,并增加一流的代理、WebSocket 隧道、Host 过滤与后台守护进程。本文是一份实操迁移指南。

你真正会用的那条一行命令

大多数 http-server 调用长这样:

http-server ./dist -p 3000

servd 的等价写法:

servd --static=./dist --port=3000

两者都在 3000 端口托管 ./dist。区别在于 servd 是单一的 Go 二进制 —— 没有 Node 进程,请求时不做 node_modules 解析,行为也不会随所装 Node 版本而漂移。

命令速查表

任务 http-server servd
托管目录 http-server ./dist servd --static=./dist
自定义端口 -p 8080 --port=8080
SPA 回退 --proxy 技巧或 -P --spa=./dist
代理某路径 --proxy=http://...(仅回退) --proxy=/api/=http://...
WebSocket 代理 不支持 --ws=/ws=ws://...
CORS --cors --cors=*--cors=<origin>
HTTPS --cert/--key --tls-cert/--tls-key
Host 过滤 不支持 --host=example.com
后台 + 重启 不支持 --daemon

模型差异所在

单根 vs. 挂载。 http-server 托管一个根目录,并为磁盘上找不到的任何请求提供单一的 --proxy 回退。servd 基于挂载:你可以在一个进程里,把多个静态/SPA 根多个代理挂到不同前缀上,最长匹配的挂载胜出。这正是一个端口能同时容纳前端、API 与 WebSocket、而无需单独反向代理的原因。

SPA 回退语义。 一个常见的 http-server SPA 变通法是把未匹配的请求代理到 index.html,这也会吞掉缺失资源的真实 404servd --spa 只对「无扩展名且带 Accept: text/html」的导航回退,因此缺失的 /app.js 仍是真正的 404

压缩。 http-server 在存在时托管预压缩的 .gzservd 托管 .gz .br,在客户端接受时优先 Brotli,否则即时 gzip 压缩可压缩文本。

CORS 行为一致,但少了意外

servd --static=./dist --cors=*

http-server --cors 一样,这会加上 Access-Control-Allow-Origin。两点刻意的差异:servd 永不发送 Access-Control-Allow-Credentials(因此你不会意外暴露带凭据的跨源请求),且当某条路由是代理时,它会剥离上游的 Access-Control-* 头部,使其不被重复。

保留你所喜欢的

如果你的工作流只需要「托管一个目录」,且环境中本就有 Node,http-server 依旧很好 —— 不必急于迁移。servd 在以下场景才真正物有所值:

  • 开发时让前端、API 与 WebSocket 位于同一个源之后;
  • 需要一个自包含二进制,用于容器、CI 产物或快速的内部托管;
  • 需要一个在后台持续运行、崩溃时自我重启的预览。

迁移一个真实配置

一个用代理 API 托管 SPA 的 package.json 脚本:

{
  "scripts": {
    "serve": "http-server ./dist -p 8080 --proxy http://localhost:9000?"
  }
}

变成:

{
  "scripts": {
    "serve": "servd --spa=./dist --proxy=/api/=http://localhost:9000/api/ --port=8080"
  }
}

注意代理现在被限定在 /api/,而不再是包揽一切的回退 —— 这通常正是你本就想要的。完整参数面见 CLI 参考,逐项特性拆解见对比

博客
servd

一个由单个 Go 二进制提供的轻量静态、SPA、HTTP 与 WebSocket 服务器。

产品

资源

© 2026 servd. 依据仓库中的 MIT 类许可证发布。 文档站由 SvelteKit 构建,并由 servd 托管。