routerx: 适用于 react admin 场景的路由管理方案

基于最新的 react-router 实现的一套基于 follow 文件结构管理的路由解决方案
更新于: 2022-09-02 14:42:36
项目主页: https://github.com/afeiship/router-packages

背景

react-router 直至 v6 才算是一个不错的路由方案,我在开发的系统中,有一个 admin 系统,期望有一个可以根据目录结构管理的路由管理方案。

原则

  • 约定优于配置
  • DRY
  • 简洁,优雅

技术选型

  • webpack
  • tree-dir 遍历方案

最终选择了 tree-dir 方案,因为不依赖于 webpack,说不定 vite 方案未来真成为主流了呢?

目前的 tree-dir 方案,实际上是纯原生 nodejs 实现的一个路由映射方案,所以,与特定编译工具无关。

三件套

  • routerx-cli: 生成 .routerrc.json 文件,供项目中 routes.tsx 调用,生成 react 组件与 path 的映射
  • routerx 接收 .routerc.json 作为入参,生成 react 路由表
  • generator-router: 项目中常用的路由脚手架

后备机制

  • 有时候,纯路径映射方案是无法满足的,所以可以 export const Routes  = {} as RouterObject 方案来实现

login/__init__.tsx 示例代码 /login → / 改为根路由

// 此为伪代码
export default () => {
  return (
    <Container className="w-full h-[100vh]">
      <ReactFullImage
        animation="blur"
        src="https://tva1.js.work/large/e6c9d24egy1h5kk7oh4kaj21hw0u0aej.jpg"
      />
      <AntdFormBuilder {...opts} onFinish={handleFinish}>
        <Button className="w-full mb-4" htmlType="submit" size="large" type="primary">
          <LoginOutlined />
          登录
        </Button>
      </AntdFormBuilder>
    </Container>
  );
};

export const Routes = {
  path: '/',
};

路由表

大体文件结构如下。

├── admin
│   ├── __init__.tsx
│   ├── index.tsx
│   ├── options
│   └── users
├── login
│   ├── __init__.tsx
│   └── _misc.tsx
└── routes.tsx
import routerx from '@jswork/routerx';

const routerRC = require('./.routerc.json');
const req = (item) => require(`.${item}`);

export default routerx(routerRC, req);

约定

  • __init__.tsx: resources 模块的容器页(container/frame),用 __init__ 是为了让这个排第一个,不同于 py里的 __init__.py 作用。
  • index.tsx: 对于路由的 index:true,也是一般模块的 list 页
  • add.tsx: 添加页面
  • edit.tsx: 编辑页面
  • xyz.tsx: 其它功能页面,会自动路由
  • _misc.tsx: 以 _ 开头的页面,会自动忽略,并不会加入路由

没有 routerx

未使用 routerx 的代码如下,这还是几个模块,如果后续模块增加,这个文件会越来越大。

export default [
  {
    path: '/',
    element: <LoginFrame /> /* __init__ */,
  },
  {
    path: '/admin',
    element: <AdminFrame /> /* __init__ */,
    children: [
      {
        index: true,
        element: <AdminIndex /> /* index */,
      },
      {
        path: 'users',
        element: <UsersFrame /> /* __init__ */,
        children: [
          {
            index: true,
            element: <UsersIndex />,
          },
          {
            path: 'add',
            element: <UsersAdd />,
          },
        ],
      },
    ],
  },
];

路由使用

import { useRoutes } from 'react-router-dom';
import routes from '@/modules/routes';

function App() {
  return useRoutes(routes);
}

export default App;

工具

后面有脚手架生成示例图。

# generate a resource<users>
yo @jswork/router --resource users

# defautls
yo @jswork/router --resource users --routes_dir=src/modules/admin

参考