从108个Nginx Location到前端SPA:服务器路由的两大流派 / From 108 Nginx Locations to Frontend SPAs: Two Paradigms of Server Routing
今天在整理和排查服务器项目时,产生了一个很有意思的观察:关于 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 变成了最核心的微服务网关,以一种近乎“手工缝合”的方式,管理着庞大而复杂的业务:
- 微服务与端口精准分发 (Micro-routing to Ports):
不同的子路径被 Nginx 剥离,精准转发给本地运行在不同端口上的小微服务: /api/zhihu-immersive-reader/-> 转发至知乎沉浸阅读器服务(端口3013)/api/speech-assess/-> 转发至语音测评服务(端口3011)/api/tts-proxy/-> 转发至 TTS 代理服务(端口3012)/api/visits/-> 转发至访问统计服务(端口3017)
每一个独立功能都是一个微小的进程,Nginx 是它们的统一大门。- 静态目录交叉缝合 (Alias Mapping):
Nginx 使用alias直接接管了不同子路径的物理静态文件: /qbank/映射到/static/6767-home/qbank//archive/assets/映射到/static/6767-home/archive/assets/- 统一拦截鉴权 (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:
- Micro-routing to Ports:
Nginx dissects different sub-paths and directs them to small microservices running on various local ports: /api/zhihu-immersive-reader/-> proxied to the 知乎 reader service (Port3013)/api/speech-assess/-> proxied to the pronunciation assessment service (Port3011)/api/tts-proxy/-> proxied to the TTS proxy service (Port3012)/api/visits/-> proxied to the visitor analytics service (Port3017)
Each feature functions as an isolated process; Nginx serves as the unified entry point.- Stitching Static Directories (Alias Mapping):
Nginx usesaliasto directly handle physical static directories for distinct sub-paths: /qbank/maps to/static/6767-home/qbank//archive/assets/maps to/static/6767-home/archive/assets/- Unified Authentication (auth_request):
Security is also consolidated at the Nginx layer. For sensitive routes, Nginx intercepts requests usingauth_request /_auth_verify, redirecting internally to the auth service (Port3021) 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.