今天在整理和排查服务器项目时,产生了一个很有意思的观察:关于 Web 服务的路由管理(Routing),我们的服务器上正并存着两种截然相反的哲学。

一种是“放手”的前端单页应用(SPA),Nginx 极其简单,只做个兜底,路由全交由浏览器里的 JavaScript 处理;另一种则是“大包大揽”的 Nginx 微路由网关,Nginx 管得极其细致,甚至单个配置文件里塞了上百个 location 块。

这篇日记详细总结一下今天的发现与思考。

流派一:极致的 JS 前端路由(SPA)

在这种结构中,Nginx 扮演的只是一个“静态文件搬运工”加“终极兜底人”的角色。

以我们服务器上的两个项目为例:
1. Zashboard (mihomo.6767.chat):
它的 Nginx 配置异常干净,核心只有这一段:
nginx location / { root /home/ubuntu/workspace/ops/zashboard/current; try_files $uri $uri/ /index.html; }
当浏览器访问 /settings 或者 /connections 时,Nginx 在物理目录下找不到对应的文件或目录,就会根据 try_files 的指示,乖乖把 index.html 返回给浏览器。接着,前端 JavaScript 脚本接管一切,通过 HTML5 History API 识别当前路径,并显示对应的控制台模块。
2. Kanna (ops/kanna - 挂载于 /codex/):
这是一个基于 React 的协作工作区。前端代码中引入了 react-router-dom。所有的子路由(如 /codex/chat、/codex/settings)在浏览器端完全由 JS 路由引擎渲染。而 Nginx 只需要做最基础的反向代理,把所有流量丢给底层的 Node/Bun 进程即可。

优点:前端体验极佳,页面切换无需刷新,极度顺滑。Nginx 配置清爽。
缺点:首屏加载较重,SEO 不够友好,且所有的路由跳转逻辑都暴露在前端代码中。


流派二:极致的 Nginx 微路由网关(Micro-routing)

与 SPA 的“放权”相反,主域名 6767.chat 走的是另一条路。它的配置文件 /etc/nginx/platform/sites/6767.chat.conf 里,足足塞了 108 个 location 块。

在这里,Nginx 变成了最核心的微服务网关,以一种近乎“手工缝合”的方式,管理着庞大而复杂的业务:

  1. 微服务与端口精准分发 (Micro-routing to Ports):
    不同的子路径被 Nginx 剥离,精准转发给本地运行在不同端口上的小微服务:
  2. /api/zhihu-immersive-reader/ -> 转发至知乎沉浸阅读器服务(端口 3013)
  3. /api/speech-assess/ -> 转发至语音测评服务(端口 3011)
  4. /api/tts-proxy/ -> 转发至 TTS 代理服务(端口 3012)
  5. /api/visits/ -> 转发至访问统计服务(端口 3017)
    每一个独立功能都是一个微小的进程,Nginx 是它们的统一大门。
  6. 静态目录交叉缝合 (Alias Mapping):
    Nginx 使用 alias 直接接管了不同子路径的物理静态文件:
  7. /qbank/ 映射到 /static/6767-home/qbank/
  8. /archive/assets/ 映射到 /static/6767-home/archive/assets/
  9. 统一拦截鉴权 (auth_request):
    安全防护也由 Nginx 统一把关。比如敏感路径(如日志、监控),Nginx 会通过 auth_request /_auth_verify 拦截,内部重定向到鉴权接口(端口 3021)去校验 Cookie。通过了才放行,不通过直接在 Nginx 层返回 302 登录重定向。

优点:灵活性极高,能够把几十个完全不同语言(Node/Python/Go)、不同框架的静态网页和动态 API,天衣无缝地拼装在同一个域名和路径结构下,完美避开跨域问题,且集中控制了鉴权与安全。
缺点:Nginx 配置文件变得极度臃肿,任何细微的路径改动都需要 reload 甚至修改 Nginx,维护成本较高。

总结

这两种流派并没有优劣之分,而是为了解决不同的问题:
- 如果是一个高内聚、高交互的独立业务,SPA + 前端 JS 路由是最好的选择,干净利落。
- 如果是一个长年累月迭代、包含了无数小工具、独立脚本和微型服务的“混沌系统”,Nginx 微路由网关则是最强大的缝合剂,它能让不同技术栈的服务在同一个域名下相安无事。

今天对路由的重新梳理,让我对服务器的架构边界有了更清晰的认识。


Today, while organizing and troubleshooting the server projects, I came across a fascinating observation: when it comes to web service routing management, our server concurrently hosts two diametrically opposed philosophies.

One is the "hands-off" Frontend Single Page Application (SPA) paradigm, where Nginx remains incredibly simple and acts only as a fallback, leaving all routing logic to JavaScript in the browser. The other is the "all-inclusive" Nginx Micro-Routing Gateway approach, where Nginx micro-manages every path, packing over a hundred location blocks into a single configuration file.

Here is a detailed summary of today's discoveries and thoughts.

Paradigm 1: Extreme JS Frontend Routing (SPA)

In this setup, Nginx plays the role of a mere "static file courier" and an "ultimate safety net."

Take two projects on our server as examples:
1. Zashboard (mihomo.6767.chat):
Its Nginx config is exceptionally clean, with the core being just this block:
nginx location / { root /home/ubuntu/workspace/ops/zashboard/current; try_files $uri $uri/ /index.html; }
When a user navigates to /settings or /connections, Nginx cannot find matching files in the physical directory. Instructed by try_files, it quietly serves index.html. Browser-side JavaScript then takes over, reads the current path via the HTML5 History API, and renders the correct dashboard component.
2. Kanna (ops/kanna - mounted at /codex/):
A React-based collaborative workspace using react-router-dom. All sub-routes (e.g., /codex/chat, /codex/settings) are rendered entirely by the browser's JS routing engine. Nginx only needs to perform basic reverse proxying, tossing the traffic to the underlying Node/Bun process.

Pros: Exceptional user experience with instantaneous, refresh-free page transitions. Highly elegant Nginx configs.
Cons: Heavy initial bundle size, poor SEO friendliness, and all routing logic is exposed to client-side code.


Paradigm 2: Extreme Nginx Micro-Routing Gateway

In stark contrast to SPA's decentralization, the primary domain 6767.chat takes a completely different path. Its configuration file /etc/nginx/platform/sites/6767.chat.conf contains exactly 108 location blocks.

Here, Nginx acts as the core API Gateway, stitching a massive, sprawling list of services together by hand:

  1. Micro-routing to Ports:
    Nginx dissects different sub-paths and directs them to small microservices running on various local ports:
  2. /api/zhihu-immersive-reader/ -> proxied to the 知乎 reader service (Port 3013)
  3. /api/speech-assess/ -> proxied to the pronunciation assessment service (Port 3011)
  4. /api/tts-proxy/ -> proxied to the TTS proxy service (Port 3012)
  5. /api/visits/ -> proxied to the visitor analytics service (Port 3017)
    Each feature functions as an isolated process; Nginx serves as the unified entry point.
  6. Stitching Static Directories (Alias Mapping):
    Nginx uses alias to directly handle physical static directories for distinct sub-paths:
  7. /qbank/ maps to /static/6767-home/qbank/
  8. /archive/assets/ maps to /static/6767-home/archive/assets/
  9. Unified Authentication (auth_request):
    Security is also consolidated at the Nginx layer. For sensitive routes, Nginx intercepts requests using auth_request /_auth_verify, redirecting internally to the auth service (Port 3021) to validate cookies. It only permits traffic if authorized, returning a 302 login redirect otherwise.

Pros: Tremendous architectural flexibility. It stitches dozens of static web pages and dynamic APIs written in different languages (Node/Python/Go) and frameworks seamlessly under a single domain, bypassing CORS hurdles and centralizing security control.
Cons: The Nginx configuration becomes highly complex and bloated. Any minor path alteration requires modifying Nginx and reloading, increasing maintenance overhead.

Conclusion

Neither paradigm is superior; rather, they solve distinct problems:
- For a highly cohesive, highly interactive standalone application, SPA + frontend JS routing is the cleanest choice.
- For a "chaotic system" evolved over years, incorporating dozens of tiny tools, standalone scripts, and micro-apps, the Nginx Micro-Routing Gateway is the ultimate adhesive. It allows services of entirely different tech stacks to coexist harmoniously under one domain.

Re-evaluating routing today has given me a much clearer perspective on our server's architectural boundaries.