# 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 "" # 应该返回: ``` --- ## 🔴 **错误示例(千万不要这样写)** ```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 - 从错误中学习,让教训成为财富!* ✨📋