Files
Meshray-Manager/docs/路由注册顺序检查清单.md
T
2026-06-30 15:14:37 +08:00

214 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MeshRay 路由注册顺序检查清单
**创建时间**: 2026-03-24
**目的**: **防止再次犯同样的路由顺序错误!**
---
## ⚠️ **血的教训**
这个问题已经犯了**至少两次**
1. ❌ 在 Go Embed 最佳实践文档中,示例代码写错了顺序
2. ❌ 在实际修复 MIME 类型问题时,又犯了同样的错误
**根本原因**: 没有形成肌肉记忆,没有使用检查清单
---
## ✅ **路由注册顺序(必须遵守)**
### 正确的顺序(从高优先级到低优先级)
```go
// 1️⃣ 中间件(最优先)
s.engine.Use(middleware.RequestLogger())
s.engine.Use(middleware.CORS())
// 2️⃣ 精确路由(具体路径)
s.engine.GET("/health", healthHandler)
s.engine.POST("/api/v1/login", loginHandler)
// 3️⃣ ⭐ 静态文件目录(高优先级,必须在 NoRoute 之前)
s.engine.StaticFS("/assets", httpFS)
s.engine.StaticFS("/static", httpFS)
// 4️⃣ 通配符路由(参数路由)
s.engine.GET("/files/:filepath", fileHandler)
// 5️⃣ ⭐ NoRoute 兜底路由(最低优先级,必须最后)
s.engine.NoRoute(func(c *gin.Context) {
// SPA 路由支持
})
```
---
## 📋 **Checklist - 每次修改路由时都要检查**
### 开发阶段
- [ ] **确认路由注册顺序正确**
- [ ] StaticFS 在 NoRoute 之前
- [ ] 精确路由在 StaticFS 之前
- [ ] 中间件在最前面
- [ ] **添加注释标记**
```go
// ⭐ 重要:先注册静态文件目录(优先级高)
s.engine.StaticFS("/assets", httpFS)
// 再注册 NoRoute 处理 SPA 路由(优先级低)
s.engine.NoRoute(...)
```
---
### Code Review 阶段
- [ ] **重点检查路由顺序**
- [ ] StaticFS 是否在 NoRoute 之前?
- [ ] 是否有其他路由可能拦截静态资源?
- [ ] 注释是否清晰标明顺序要求?
- [ ] **功能测试**
- [ ] JS 文件返回 `application/javascript`
- [ ] CSS 文件返回 `text/css`
- [ ] HTML 文件返回 `text/html`
- [ ] 浏览器无 MIME 类型错误
---
### 测试验证
**快速测试命令**:
```bash
# 测试 JS 文件 MIME 类型
curl -I http://localhost:9531/assets/index.js | grep Content-Type
# 应该返回:application/javascript
# 测试 CSS 文件 MIME 类型
curl -I http://localhost:9531/assets/style.css | grep Content-Type
# 应该返回:text/css
# 测试 HTML 页面
curl http://localhost:9531 | grep "<!DOCTYPE html>"
# 应该返回:<!DOCTYPE html>
```
---
## 🔴 **错误示例(千万不要这样写)**
```go
// ❌ 错误示范 - 这个顺序会导致静态文件全部返回 HTML!
if staticFS != nil {
httpFS := http.FS(staticFS)
// ❌ 先注册 NoRoute(错误!)
s.engine.NoRoute(func(c *gin.Context) {
// 所有请求都被这里拦截
})
// ❌ 后注册 StaticFS(永远不会被执行)
s.engine.StaticFS("/assets", httpFS)
}
```
**后果**:
- ❌ 所有 `/assets/*.js` 返回 HTML
- ❌ 所有 `/assets/*.css` 返回 HTML
- ❌ 浏览器控制台大量 MIME 类型错误
- ❌ 前端完全无法使用
---
## 🟢 **正确示例(必须这样写)**
```go
// ✅ 正确示范 - 严格按照优先级顺序
if staticFS != nil {
httpFS := http.FS(staticFS)
// ✅ 先注册静态文件目录(高优先级)
s.engine.StaticFS("/assets", httpFS)
s.engine.StaticFS("/static", httpFS)
// ✅ 再注册 NoRoute(低优先级)
s.engine.NoRoute(func(c *gin.Context) {
// SPA 路由支持
})
}
```
**效果**:
- ✅ JS 文件正确返回 `application/javascript`
- ✅ CSS 文件正确返回 `text/css`
- ✅ HTML 文件正确返回 `text/html`
- ✅ 前端正常工作
---
## 📊 **记忆口诀**
> **中间件最先注册,精确路由紧随其后;**
> **静态文件要提前,NoRoute 最后面;**
> **顺序千万别搞反,否则资源全完蛋!**
---
## 🎯 **如何形成肌肉记忆**
### 1. 每次写路由时都大声念出口诀
```
"静态文件要提前,NoRoute 最后面"
```
### 2. 在代码模板中固化顺序
创建代码片段(VSCode Snippet:
```go
// Gin 路由模板
if staticFS != nil {
httpFS := http.FS(staticFS)
// ⭐ 重要:先注册静态文件目录(优先级高)
${1:s.engine.StaticFS("/assets", httpFS)}
// 再注册 NoRoute 处理 SPA 路由(优先级低)
${2:s.engine.NoRoute(...)}
}
```
### 3. 在 IDE 中设置警告
如果使用 VSCode,可以创建自定义规则检测路由顺序。
---
## 📈 **历史错误记录**
| 时间 | 错误 | 影响 | 改进措施 |
|------|------|------|----------|
| 2026-03-24 (Go Embed 文档) | 示例代码顺序错误 | 文档误导他人 | 已修正并添加警告 |
| 2026-03-24 (MIME 修复) | 实际修复时顺序错误 | 前端无法访问 | 已修正并创建本清单 |
---
## ✅ **承诺**
从今天起,每次修改路由注册时都要:
1. 📝 **先看这个 Checklist**
2. 🔍 **检查顺序是否正确**
3. 🧪 **运行测试命令验证**
4. 📋 **Code Review 时重点检查**
**不再犯同样的错误!**
---
**状态**: ✅ **Checklist 已创建**
**执行**: 每次修改路由时必须使用此清单
*MeshRay - 从错误中学习,让教训成为财富!* ✨📋