
Security News
Browserslist-rs Gets Major Refactor, Cutting Binary Size by Over 1MB
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
@soybean-react/vite-plugin-react-router
Advanced tools
English | δΈζ
ElegantRouter is a tool for creating routes based on the file system, which can automatically generate route definitions, route file imports and route-related type definitions. Just create the route file according to the agreed rules, without adding any additional configuration in the route file.
The main difference between ElegantRouter and other file system-based routing tools is that:
Taking configuring react routes as an example, the traditional way of creating page routes requires the following steps:
Although these steps are not complicated, in actual development, they are repetitive and need to be done manually. In addition, the maintenance of route names and paths is very troublesome, there is no clear agreement on the route definition of the layout and page components, resulting in a messy route definition. And using ElegantRouter, you only need to create the route file according to the agreed rules, you can automatically generate the route in the specified route file.
You only need to create a route file according to the agreed rules to generate the route in the specified route file.
pnpm install @ohh-889/react-auto-route
react-router-dom
export function Component() {
return <div>Component</div>;
}
1. Override the lazy method
lazy:async ()=>{
const component=await import('@/views/Component.tsx')
return {
Component:component.default
ErrorBoundary:ErrorBoundary,
}
// or you can use the following code
const Component=component.default
return {
element:<Component />,
ErrorBoundary:ErrorBoundary,
}
}
2. Handle route lazy loading by yourself
optsunstable_datastrategy
react-soybean-admin
Source of inspiration
elegant-router best practice
soybean-admin
Preview address
- This is a 'vue' technology stack back-end management system project
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import ElegantVueRouter from "@@ohh-889/react-auto-route";
export default defineConfig({
plugins: [
react(),
ElegantreactRouter({
alias: {
"@": "src",
},
layouts: {
base: "src/layouts/base-layout/index.tsx",
blank: "src/layouts/blank-layout/index.tsx",
},
}),
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
src/router/routes/index.ts
import type { ElegantRoute, CustomRoute } from "@elegant-router/types";
import { generatedRoutes } from "../elegant/routes";
import { layouts, views } from "../elegant/imports";
import { transformElegantRoutesToReactRoutes } from "../elegant/transform";
const customRoutes: CustomRoute[] = [
{
name: "root",
path: "/",
redirectTo: '/home',
},
{
name: "not-found",
path: "*",
component: "$view.404",
},
];
const elegantRoutes: ElegantRoute[] = [...customRoutes, ...generatedRoutes];
export const routes = transformElegantRoutesToreactRoutes(
elegantRoutes,
layouts,
views
);
src/router/index.ts
import {createBrowserRouter} from 'react-router-dom'
import { routes } from "./routes";
export const router=createBrowserRouter(builtinRoutes)
src/App.tsx
import { RouterProvider } from 'react-router-dom';
import { router } from "@/router";
const App = () => {
return <RouterProvider router={reactRouter} />
}
After starting the project, the plugin will automatically generate the src/router/elegant directory, and the files in this directory are the automatically generated route import, route definition and route transformation files.
You can configure pagePatterns
to specify the rules for creating route files. The rules for creating route files are regular expressions, and if the path of a route file matches the regular expression, the route file will be created.
Default: all files named index.tsx
γ[id].tsx
γ[module].tsx
, etc. below the folder.
pagePatterns: ["**β/index.tsx", "**β/[[]*[]].tsx"];
views
βββ about
β βββ index.tsx
{
name: 'about',
path: '/about',
component: 'layout.base$view.about',
meta: {
title: 'about'
}
},
it is a single level route, to add layout, the component props combines the layout and view component, split by the dollar sign "$"
{
path: '/about',
component: BaseLayout,
ErrorBoundary: ErrorBoundary,
children: [
{
id: 'about',
index:true,
lazy: () => import('@/pages/about/index.tsx'),
handle: {
title: 'about'
}
}
]
},
views
βββ list
β βββ home
β β βββ index.tsx
β βββ detail
β β βββ index.tsx
Please don't have the following index.tsx on the same level as the folder, this is not part of the agreed upon rules
Error example
views
βββ list
β βββ index.tsx
β βββ detail
β β βββ index.tsx
{
name: 'list',
path: '/list',
component: 'layout.base',
meta: {
title: 'list'
},
children: [
{
name: 'list_home',
path: 'home',
component: 'view.list_home',
meta: {
title: 'list_home'
}
},
{
name: 'list_detail',
path: 'detail',
component: 'view.list_detail',
meta: {
title: 'list_detail'
}
},
]
}
There are two layers of route data for secondary routes, the first layer of route is the layout component and the second layer of route is the page component
{
name: 'list',
path: '/list',
component: BaseLayout,
ErrorBoundary: ErrorBoundary,
loader: ()=>redirect('/list/home'),
handle: {
title: 'list'
},
children: [
{
name: 'list_home',
path: 'home',
lazy: () => import('@/views/list/home/index.tsx'),
handle: {
title: 'list_home'
}
},
{
name: 'list_detail',
path: 'detail',
lazy: () => import('@/views/list/detail/index.tsx'),
handle: {
title: 'list_detail'
}
}
]
},
the first layer of route data contains the redirection configuration, which by default redirects to the first sub-route
views
βββ multi-menu
β βββ first
β β βββ child
β β β βββ index.tsx
β βββ second
β β βββ child
β β β βββ home
β β β β βββ index.tsx
views
βββ multi-menu
β βββ first_child
β β βββ index.tsx
β βββ second_child_home
β β βββ index.tsx
The route hierarchy is split by the underscore symbol "_", which prevents the folder hierarchy from being too deep.
{
name: 'multi-menu',
path: '/multi-menu',
component: 'layout.base',
meta: {
title: 'multi-menu'
},
children: [
{
name: 'multi-menu_first',
path: 'first',
meta: {
title: 'multi-menu_first'
},
children: [
{
name: 'multi-menu_first_child',
path: 'child',
component: 'view.multi-menu_first_child',
meta: {
title: 'multi-menu_first_child'
}
}
]
},
{
name: 'multi-menu_second',
path: 'second',
meta: {
title: 'multi-menu_second'
},
children: [
{
name: 'multi-menu_second_child',
path: 'child',
meta: {
title: 'multi-menu_second_child'
},
children: [
{
name: 'multi-menu_second_child_home',
path: 'home',
component: 'view.multi-menu_second_child_home',
meta: {
title: 'multi-menu_second_child_home'
}
}
]
}
]
}
]
}
if the route level is greater than 2, the generated route data is a recursive structure
{
name: 'multi-menu',
path: '/multi-menu',
component: BaseLayout,
redirect: {
name: 'multi-menu_first'
},
meta: {
title: 'multi-menu'
},
children: [
{
name: 'multi-menu_first',
path: 'first',
loader:()=>redirect('child')},
handle: {
title: 'multi-menu_first'
},
children: [
{
name: 'multi-menu_first_child',
path: 'child',
lazy: () => import('@/views/multi-menu/first_child/index.tsx'),
handle: {
title: 'multi-menu_first_child'
}
},
]
},
{
name: 'multi-menu_second',
path: 'second',
loader:()=>redirect('child'),
handle: {
title: 'multi-menu_second'
},
children:[
{
name: 'multi-menu_second_child',
path: 'child',
loader:()=>redirect('home'),
handle: {
title: 'multi-menu_second_child'
},
children:[
{
name: 'multi-menu_second_child_home',
path: 'home',
lazy: () => import('@/views/multi-menu/second_child_home/index.tsx'),
handle: {
title: 'multi-menu_second_child_home'
}
}
]
},
]
},
]
},
meta
import { useMatches } from "react-router-dom";
const matches = useMatches();
const meta= matches[matches.length - 1].handle;
the transformed react routes only has two levels, the first level is the layout component, and the second level is the redirect routes or the page routes
Folder names that begin with an underscore "_" will be ignored
views
βββ _error
β βββ 403
β β βββ index.tsx
β βββ 404
β β βββ index.tsx
β βββ 500
β β βββ index.tsx
{
name: '403',
path: '/403',
component: 'layout.base$view.403',
meta: {
title: '403'
}
},
{
name: '404',
path: '/404',
component: 'layout.base$view.404',
meta: {
title: '404'
}
},
{
name: '500',
path: '/500',
component: 'layout.base$view.500',
meta: {
title: '500'
}
},
views
βββ user
β βββ [id].tsx
{
name: 'user',
path: '/user/:id',
component: 'layout.base$view.user',
props: true,
meta: {
title: 'user'
}
}
import type { RouteKey } from "@elegant-router/types";
ElegantreactRouter({
routePathTransformer(routeName, routePath) {
const routeKey = routeName as RouteKey;
if (routeKey === "user") {
return "/user/:id(\\d+)";
}
return routePath;
},
});
the custom route is only used to generate the route declaration, and the route file is not generated, you should create the route file manually.
ElegantreactRouter({
customRoutes: {
map: {
root: "/",
notFound: "*",
},
names: ["two-level_route"],
},
});
Generated CustomRouteKey
type RouteMap = {
root: "/";
notFound: "*";
"two-level": "/two-level";
"two-level_route": "route";
};
type CustomRouteKey = "root" | "notFound" | "two-level" | "two-level_route";
it can use existing page components as the route component
import type { CustomRoute } from "@elegant-router/types";
const customRoutes: CustomRoute[] = [
{
name: "root",
path: "/",
redirectTo: {
name: "403",
},
},
{
name: "not-found",
path: "*",
component: "layout.base$view.404",
},
{
name: "two-level",
path: "/two-level",
component: "layout.base",
children: [
{
name: "two-level_route",
path: "/two-level/route",
component: "view.about",
},
],
},
];
ElegantRouterOption
:
property | instruction | type | default value |
---|---|---|---|
cmd | the root directory of the project | string | process.cwd() |
pageDir | the relative path to the root directory of the pages | string | "src/views" |
alias | alias, it can be used for the page and layout file import path | Record<string, string> | { "@": "src" } |
pagePatterns | the patterns to match the page files (the match syntax follow micromatch) | string[] | ["**β/index.react", "**β/[[]*[]].react"] |
pageExcludePatterns | the patterns to exclude the page files (The default exclusion folder components is used as the routing page file.) | string[] | ["**β/components/**"] |
routeNameTransformer | transform the route name (The default is the name of the folder connected by an underscore) | (routeName: string) => string | routeName => routeName |
routePathTransformer | transform the route path | (transformedName: string, path: string) => string | (_transformedName, path) => path |
ElegantreactRouterOption
:
extends
ElegantRouterOption
property | instruction | type | default value |
---|---|---|---|
dtsDir | the declaration file directory of the generated routes | string | "src/typings/elegant-router.d.ts" |
importsDir | the directory of the imports of routes | string | "src/router/elegant/imports.ts" |
lazyImport | whether the route is lazy import | (routeName: string) => boolean | _name => true |
constDir | the directory of the route const | string | "src/router/elegant/routes.ts" |
customRoutes | define custom routes, which's route only generate the route declaration | { map: Record<string, string>; names: string[] } | { map: { root: "/", notFound: "*" }, names: []} |
layouts | the name and file path of the route layouts | Record<string, string> | { base: "src/layouts/base-layout/index.tsx", blank: "src/layouts/blank-layout/index.tsx" } |
defaultLayout | the default layout name used in generated route const ( takes the first layout of layouts by default.) | string | "base" |
layoutLazyImport | whether the route is lazy import | (layoutName: string) => boolean | _name => false |
transformDir | the directory of the routes transform function (Converts the route definitions of the generated conventions into routes for the react-router.) | string | "src/router/elegant/transform.ts" |
onRouteMetaGen | the route meta generator | (routeName: string) => Record<string, string> | routeName => ({ title: routeName }) |
Folder naming: can only contain letters, numbers, dash, underscore, and no other special characters
The underscore is a cut identifier for the routing hierarchy, and the short horizontal line is used to connect multiple words in a one-level route
|
Ohh 1509326266@qq.com https://github.com/mufeng889 |
FAQs
A plugin to create router elegantly
The npm package @soybean-react/vite-plugin-react-router receives a total of 78 weekly downloads. As such, @soybean-react/vite-plugin-react-router popularity was classified as not popular.
We found that @soybean-react/vite-plugin-react-router demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Research
Security News
Eight new malicious Firefox extensions impersonate games, steal OAuth tokens, hijack sessions, and exploit browser permissions to spy on users.
Security News
The official Go SDK for the Model Context Protocol is in development, with a stable, production-ready release expected by August 2025.