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

5.2 KiB
Raw Blame History

MeshRay 路由注册顺序检查清单

创建时间: 2026-03-24
目的: 防止再次犯同样的路由顺序错误!


⚠️ 血的教训

这个问题已经犯了至少两次

  1. 在 Go Embed 最佳实践文档中,示例代码写错了顺序
  2. 在实际修复 MIME 类型问题时,又犯了同样的错误

根本原因: 没有形成肌肉记忆,没有使用检查清单


路由注册顺序(必须遵守)

正确的顺序(从高优先级到低优先级)

// 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 之前
    • 中间件在最前面
  • 添加注释标记

    // ⭐ 重要:先注册静态文件目录(优先级高)
    s.engine.StaticFS("/assets", httpFS)
    
    // 再注册 NoRoute 处理 SPA 路由(优先级低)
    s.engine.NoRoute(...)
    

Code Review 阶段

  • 重点检查路由顺序

    • StaticFS 是否在 NoRoute 之前?
    • 是否有其他路由可能拦截静态资源?
    • 注释是否清晰标明顺序要求?
  • 功能测试

    • JS 文件返回 application/javascript
    • CSS 文件返回 text/css
    • HTML 文件返回 text/html
    • 浏览器无 MIME 类型错误

测试验证

快速测试命令:

# 测试 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>

🔴 错误示例(千万不要这样写)

// ❌ 错误示范 - 这个顺序会导致静态文件全部返回 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 类型错误
  • 前端完全无法使用

🟢 正确示例(必须这样写)

// ✅ 正确示范 - 严格按照优先级顺序
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:

// 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 - 从错误中学习,让教训成为财富! 📋