Skyroc Admin React

常见问题

排查菜单、动态路由、刷新 404、代理、token、Vite 预设构建和 devtools 初始化顺序问题

这一页用于快速定位 apps/admin 二次开发时最常见的问题。每个问题都先给排查路径,再指向更完整的专题页面。

如果一个问题同时涉及路由、菜单、权限和请求,优先按当前启动链路理解:

main.tsx
  -> bootstrap.tsx
    -> setupTheme()
    -> setupAdminLayouts()
    -> setupAdminPlugins()
    -> setupI18n()
    -> render <App />

App.tsx
  -> QueryClientProvider
  -> Jotai Provider
  -> AdminDevtoolsProvider
  -> AntdProvider
  -> NotificationProvider
  -> RouterProvider

快速索引

现象先看哪里
菜单不显示VITE_AUTH_ROUTE_MODEsetupAdminLayoutsuseAuth().initAuth()、页面 staticData.menu
动态路由点击后 404后端路由 path 是否有前端页面文件和 routeTree.gen.ts 对应
刷新页面 404生产静态服务是否配置 history rewrite
代理失败VITE_HTTP_PROXYVITE_SERVICE_BASE_URLVITE_OTHER_SERVICE_BASE_URL、是否重启 Vite
token 异常localStgsetAuth()、请求 adapter、业务 code 配置
启动时 Vite 预设未构建predev / prebuild 是否执行了 build:admin-vite
devtools 或 NProgress 顺序异常main.tsxbootstrap.tsxsetupAdminPlugins() 的执行顺序

菜单不显示

先判断当前是静态菜单还是动态菜单:

VITE_AUTH_ROUTE_MODE=static

当前默认是 static。静态模式下,菜单来自前端 routeTree 和路由 staticData;动态模式下,菜单来自 fetchGetBackendRoutes() 返回的后端路由树,再结合前端 route tree 做权限和路径匹配。

静态模式排查

检查项说明
页面位置后台页面应放在 apps/admin/src/pages/(admin) 下。
路由生成apps/admin/src/features/router/routeTree.gen.ts 是否包含新页面。
元信息页面 createFileRoute() 是否配置了 staticData
菜单配置staticData.menu 是否存在,且没有被设为隐藏。
权限staticData.permissions 是否允许当前用户角色,或当前用户是否有 VITE_STATIC_SUPER_ROLE
分类当前 menuCategories 只有 admin -> /(admin),页面是否挂在这个后台 layout 下。
初始化登录后是否成功执行 useAuth().initAuth(),并调用 initMenus(data)

最小页面结构参考:

import { createFileRoute } from '@tanstack/react-router';

const DemoPage = () => {
  return <div>Demo</div>;
};

export const Route = createFileRoute('/(admin)/demo')({
  component: DemoPage,
  staticData: {
    i18nKey: 'route.demo',
    icon: 'mdi:view-dashboard',
    menu: {
      order: 10
    },
    title: 'Demo'
  }
});

如果页面能直接访问但菜单不出现,通常是 staticData.menu、权限或菜单分类问题。如果页面本身也 404,先排查路由文件和 routeTree.gen.ts

动态模式排查

动态模式要同时满足两件事:

  1. 后端接口返回了可访问的菜单路由。
  2. 前端存在同路径页面,route tree 能匹配它。

相关实现位置:

文件职责
apps/admin/src/service/api/route/api.tsfetchGetBackendRoutes() 请求 /route/getReactUserRoutes
packages/@core/types/src/api/route.d.ts定义后端原始路由响应和适配后的动态路由结构。
apps/admin/src/features/menus/dynamic-routes.ts把后端 name/path/component/handle 响应适配成布局运行时需要的动态菜单数据。
apps/admin/src/bootstrap.tsx通过 loadDynamicRoutesloadAdminDynamicRoutes() 注入布局运行时。
packages/web/admin-layouts/src/features/menus/*根据动态路由、权限和 route tree 生成菜单。

后端返回的 path 必须能和前端 apps/admin/src/pages 生成的 route tree 对上。只返回菜单数据但前端没有对应页面文件,点击后仍然会 404。

动态路由失效

动态路由失效通常不是一个单点问题,要按四层看:

层级关键问题
envVITE_AUTH_ROUTE_MODE 是否为 dynamic
接口/route/getReactUserRoutes 是否返回当前用户的路由树。
前端页面apps/admin/src/pages 下是否存在对应 path 的页面。
权限permissions、用户角色、hasAuthorizedRoutePath() 是否允许访问。

如果菜单展示了,但点击进入 404,优先检查后端返回的 path 和前端路由路径是否一致。动态菜单不是运行时动态加载任意页面,它只是决定“哪些已存在的前端页面可见、可访问”。

如果菜单不展示,先看 queryMenusOptions() 是否真正发起请求。当前实现只有在已有用户信息时才启用菜单查询:

const enabled = Boolean(queryClient.getQueryData(AUTH_QUERY_KEYS.USER_INFO));

因此用户信息初始化失败时,动态菜单也不会生成。

刷新页面 404

开发环境由 Vite dev server 承接前端路由。生产环境如果使用 history 路由,刷新深层路径时必须由静态服务回退到 index.html

正确的 Nginx 根路径配置:

location / {
  try_files $uri $uri/ /index.html;
}

子路径部署时,回退路径也要带子路径:

location /admin/ {
  try_files $uri $uri/ /admin/index.html;
}

同时确认构建 base:

VITE_BASE_URL=/admin/

只配置 rewrite,不配置正确的 VITE_BASE_URL,会导致刷新能回到 index.html,但静态资源仍然 404。

代理失败

先区分开发代理和生产代理。

开发代理只在 vite dev 中生效:

VITE_HTTP_PROXY=Y
VITE_PROXY_LOG=Y
VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
VITE_OTHER_SERVICE_BASE_URL={ demo: "http://localhost:9528" }

请求层在开发环境且 VITE_HTTP_PROXY=Y 时,会把主服务改成:

/proxy-default

其他服务按 key 改成:

/proxy-{key}

@skyroc/web-admin-vite 再在 Vite dev server 中把这些前缀转发到真实地址。

常见检查项:

现象检查
请求没有走 /proxy-default当前是否是 dev 环境,VITE_HTTP_PROXY 是否为 Y
终端没有代理日志VITE_PROXY_LOG 是否为 Y
其他服务代理不存在VITE_OTHER_SERVICE_BASE_URL 是否是合法 JSON5,key 是否和请求实例使用的 key 一致。
改 env 后仍旧请求旧地址Vite env 启动时读取,改完要重启 dev server。
生产环境 /proxy-default 404生产没有 Vite dev server proxy,改 .env.prod 或配置 Nginx 反向代理。

token 异常

当前认证状态分为三块:

位置职责
apps/admin/src/features/auth/use-auth.tsJotai auth state,登录后保存 token,退出时清理状态和菜单。
apps/admin/src/features/auth/shared.tslocalStg 读取和清理 token。
apps/admin/src/service/adapter.ts请求 adapter,提供 getToken()getRefreshToken()setAuth()resetAuth()redirectToLogin()
packages/@core/service/src/request/*统一添加 Authorization,处理登出码、弹窗登出码和 token 过期刷新。

登录成功后会执行:

setAuth(data);
const info = await initAuth();

setAuth() 会保存:

token
refreshToken

请求层会把 token 转成:

Authorization: Bearer {token}

如果登录后马上又回到登录页,先检查:

检查项说明
登录接口返回是否包含 tokenrefreshToken
用户信息接口initAuth() 内的 queryUserInfoOptions() 是否成功。
存储前缀VITE_STORAGE_PREFIX 是否变化,导致读写的 localStorage key 不一致。
业务 codeVITE_SERVICE_SUCCESS_CODE 是否和后端成功 code 一致。
登出 codeVITE_SERVICE_LOGOUT_CODESVITE_SERVICE_MODAL_LOGOUT_CODES 是否误命中。
过期 codeVITE_SERVICE_EXPIRED_TOKEN_CODES 是否和后端 token 过期 code 一致。

如果刷新后变成未登录,检查浏览器 localStorage 中对应 VITE_STORAGE_PREFIX 下的 token 是否存在。

Vite 预设未构建

apps/admin/vite.config.ts@skyroc/web-admin-vite 导入:

import { defineConfig } from '@skyroc/web-admin-vite';

因此启动和构建前都需要先构建这个 workspace 包。apps/admin/package.json 已经配置了:

{
  "predev": "pnpm run build:admin-vite",
  "prebuild": "pnpm run build:admin-vite",
  "prepreview": "pnpm run build:admin-vite"
}

推荐命令:

pnpm --filter skyroc-admin dev
pnpm --filter skyroc-admin build
pnpm --filter skyroc-admin preview

如果你绕过 package script 直接运行 vite,就不会自动触发这些 pre* 脚本。遇到预设产物缺失时,先执行:

pnpm --filter skyroc-admin build:admin-vite

devtools 初始化顺序

当前入口顺序是有意设计的:

阶段位置作用
1main.tsx开发环境先加载 @skyroc/web-admin-devtools/jotai,再进入 bootstrap.tsx
2bootstrap.tsx初始化 theme、layout runtime、plugins、i18n。
3App.tsx挂载 Query、Jotai、AdminDevtools、Antd、Notification、Router。

如果 devtools、Jotai 面板或 Router 面板异常,先确认是否改动了入口顺序。@skyroc/web-admin-devtools/jotai 需要在应用 Provider 挂载前加载,否则 Jotai 调试能力可能拿不到正确上下文。

NProgress 也依赖初始化顺序。globalConfig.nprogress 读取前,必须先由 setupAdminPlugins() 调用 initNProgress()。如果提前读取,会触发:

nprogress is not initialized, please call initNProgress function first

这类问题不要通过吞错误处理。应回到 bootstrap.tsxplugins 初始化链路,确认初始化发生在路由和页面副作用之前。

修改后仍无效

按这个顺序缩小范围:

  1. 确认改的是 apps/admin 当前使用的文件,不是旧 Vue 文档或旧 React 文档里的路径。
  2. 确认 env 修改后已经重启 dev server,生产 env 修改后已经重新 build。
  3. 确认 routeTree.gen.ts 已经随页面文件变化重新生成。
  4. 确认登录用户信息、角色、权限和后端动态路由数据符合预期。
  5. 确认问题发生在开发环境还是生产静态服务,代理和 rewrite 的排查路径不同。

相关链接

内容页面
启动和构建命令快速开始
env 与 Vite 配置环境变量与 Vite
路由文件和 route tree路由概览
路由元信息和菜单字段路由元信息
登录守卫路由守卫
权限和 403权限
错误页、404 和 loading错误与加载页
部署、base 和 Nginx rewrite构建部署

On this page