生成的Vite基于文件的路由
自从尝试Next.js(页面目录)以来,我喜欢使用基于文件的路由。在使用VITE和客户端应用程序应用相同的概念之后,我开始编写博客文章,涵盖了用React路由器实现基于客户端的文件路由器的文章,该路由器后来包装为generouted 。
今天的generouted带来了许多功能,支持多个框架和路由器,并激发了Next.js,Remix,Expo,Docusaurus,Sveltekit等的想法和惯例。
generouted使用Vite的Glob Import API列出src/pages目录中的路由,并根据generouted的公约生成路由树和模态。
还可以通过代码生成来提供某些集成的Vite插件来提供类型安全组件/钩/utils。
react-router-dom或@tanstack/router ?或@tanstack/react-location@solidjs/router的坚实支持@mdx-js/rollup安装和设置generouted的互动游乐场src/pages/ files,然后查看反映的更改如果您没有带有React和打字稿的Vite项目,请检查Vite文档以启动一个新项目。
pnpm add @generouted/react-router react-router-dom // vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import generouted from '@generouted/react-router/plugin'
export default defineConfig ( { plugins : [ react ( ) , generouted ( ) ] } ) // src/main.tsx
import { createRoot } from 'react-dom/client'
import { Routes } from '@generouted/react-router'
createRoot ( document . getElementById ( 'root' ) ! ) . render ( < Routes /> ) 通过创建新文件src/pages/index.tsx → / ,然后导出默认组件:
export default function Home ( ) {
return < h1 > Home </ h1 >
}检查下面的路由约定部分。
您可以在@generouted/react-router文档上找到有关类型安全导航和全局模式的更多详细信息。
如果您没有具有固体和打字稿的Vite项目,请检查Vite文档以启动一个新项目。
pnpm add @generouted/solid-router @solidjs/router // vite.config.ts
import { defineConfig } from 'vite'
import solid from 'vite-plugin-solid'
import generouted from '@generouted/solid-router/plugin'
export default defineConfig ( { plugins : [ solid ( ) , generouted ( ) ] } ) // src/main.tsx
import { render } from 'solid-js/web'
import { Routes } from '@generouted/solid-router'
render ( Routes , document . getElementById ( 'root' ) ! ) 通过创建新文件src/pages/index.tsx → / ,然后导出默认组件:
export default function Home ( ) {
return < h1 > Home </ h1 >
}请参阅下面有关generouted路由约定的更多信息。
您可以在@generouted/solid-router文档上找到有关类型安全导航和全局模式的更多详细信息。
在这里查看文档
如果您没有带有React和打字稿的Vite项目,请检查Vite文档以启动一个新项目。
pnpm add generouted @tanstack/react-location // src/main.tsx
import { createRoot } from 'react-dom/client'
import { Routes } from 'generouted/react-location'
createRoot ( document . getElementById ( 'root' ) ! ) . render ( < Routes /> ) 通过创建新文件src/pages/index.tsx → / ,然后导出默认组件:
export default function Home ( ) {
return < h1 > Home </ h1 >
} src/pages的路线声明.tsx , .jsx和.mdx文件扩展src/pages/_app.tsx用于应用程序级别的布局src/pages/404.tsx用于自定义非创建页面src/pages/index.tsx → /src/pages/posts/index.tsx → /posts src/pages/posts/2022/index.tsx → /posts/2022src/pages/posts/2022/resolutions.tsx → /posts/2022/resolutions src/pages/posts/[slug].tsx → /posts/:slugsrc/pages/posts/[slug]/tags.tsx /posts/:slug/tagssrc/pages/posts/[...all].tsx → /posts/* _layout.tsx → src/pages/posts/_layout.tsx<Outlet />组件来渲染布局儿童src/pages/posts/目录中的所有文件都将使用该布局包装.在要转换为前向斜线的细分之间src/pages/posts.nested.as.url.not.layout.tsx → /posts/nested/as/url/not/layout ()src/pages/(auth)/_layout.tsxsrc/pages/(auth)/login.tsx /login+前缀(认为模态是覆盖当前路线的额外路线)useModals()挂钩可用的模态导航src/pages/+info.tsx → /infosrc/pages/+checkout/+details.tsx → /checkout/detailssrc/pages/+checkout/+payment.tsx → /checkout/payment -认为可以从路由路径中减去或删除该段)src/pages/-en/about.tsx → /en?/about → /en/about , /aboutsrc/pages/-[lang]/about.tsx /:lang?/about /en/about , /fr/about , /about _开始src/pages/_ignored.tsxsrc/pages/posts/_components/button.tsxsrc/pages/posts/_components/link.tsxexport default Component() {...}export const Loader = () => {...}export const Action = () => {...}export const Pending = () => {...}export const Catch = () => {...}src/pages
├── (auth)
│ ├── _layout.tsx
│ ├── login.tsx
│ └── register.tsx
├── blog
│ ├── _components
│ │ ├── button.tsx
│ │ └── comments.tsx
│ ├── [...all].tsx
│ ├── [slug].tsx
│ ├── _layout.tsx
│ ├── index.tsx
│ └── tags.tsx
├── docs
│ ├── -[lang]
│ │ ├── index.tsx
│ │ └── resources.tsx
│ └── -en
│ └── contributors.tsx
├── +info.tsx
├── 404.tsx
├── _app.tsx
├── _ignored.tsx
├── about.tsx
├── blog.w.o.layout.tsx
└── index.tsx| 文件 | 小路 | 习俗 |
|---|---|---|
(auth)/_layout.tsx | 无路的布局组 | |
(auth)/login.tsx | /login | 常规路线 |
(auth)/register.tsx | /register | 常规路线 |
blog/_components/button.tsx | 通过忽略的目录忽略了路线 | |
blog/_components/comments.tsx | 通过忽略的目录忽略了路线 | |
blog/[...all].tsx | /blog/* | 动态捕获的路线 |
blog/[slug].tsx | /blog/:slug | 动态路线 |
blog/_layout.tsx | /blog路线的布局 | |
blog/index.tsx | /blog | 索引路线 |
blog/tags.tsx | /blog/tags | 常规路线 |
docs/-[lang]/index.tsx | /docs/:lang?/index | 可选的动态路线段 |
docs/-[lang]/resources.tsx | /docs/:lang?/resources | 可选的动态路线段 |
docs/-en/contributors.tsx | /docs/en?/contributors | 可选的静态路线部分 |
+info.tsx | /info | 模态路线 |
404.tsx | * | 自定义404 (可选) |
_app.tsx | 自定义app布局(可选) | |
_ignored.tsx | 忽略路线 | |
about.tsx | /about | 常规路线 |
blog.wolayout.tsx | /blog/w/o/layout | 没有/blog布局的路线 |
index.tsx | / | 索引路线 |
通过@generouted/react-router或@generouted/solid-router
<Routes /> - 基于文件的路由组件将在应用程序条目中呈现routes - 默认情况下使用的基于文件的路由树 /对象<Routes />组件通过@generouted/react-router/lazy或@generouted/solid-router/lazy
@generouted/react-router或@generouted/solid-router启用懒惰加载src/pages/_app.tsx<Routes />和routes导出通过@generouted/react-router/plugin或@generouted/solid-router/plugin
src/router.ts文件<Link> , <Navigate> , useModals() , useNavigate() , useParams() , redirect() ,等。@generouted/react-router文档或@generouted/solid-router docs有关更多详细信息通过@generouted/react-router/core或@generouted/solid-router/core
<Routes/>组件使用可用的集成目录有多种方法可以实现这一目标。如果您希望在一个地方处理逻辑,则可以在组件中使用重定向处理来定义受保护的路由:
// src/config/redirects.tsx
import { Navigate , useLocation } from 'react-router-dom'
import { useAuth } from '../context/auth'
import { Path } from '../router'
const PRIVATE : Path [ ] = [ '/logout' ]
const PUBLIC : Path [ ] = [ '/login' ]
export const Redirects = ( { children } : { children : React . ReactNode } ) => {
const auth = useAuth ( )
const location = useLocation ( )
const authenticatedOnPublicPath = auth . active && PUBLIC . includes ( location . pathname as Path )
const unAuthenticatedOnPrivatePath = ! auth . active && PRIVATE . includes ( location . pathname as Path )
if ( authenticatedOnPublicPath ) return < Navigate to = "/" replace />
if ( unAuthenticatedOnPrivatePath ) return < Navigate to = "/login" replace />
return children
}然后在根级布局src/pages/_app.tsx上使用该组件( <Redirects> )来包装<Outlet>组件:
// src/pages/_app.tsx
import { Outlet } from 'react-router-dom'
import { Redirects } from '../config/redirects'
export default function App ( ) {
return (
< section >
< header >
< nav > ... </ nav >
</ header >
< main >
< Redirects >
< Outlet />
</ Redirects >
</ main >
</ section >
)
}您可以在渲染模板上找到此方法的完整示例
您可以使用导出的routes对象自定义路由器或使用哈希/内存路由器:
import { createRoot } from 'react-dom/client'
import { RouterProvider , createHashRouter } from 'react-router-dom'
import { routes } from '@generouted/react-router'
const router = createHashRouter ( routes )
const Routes = ( ) => < RouterProvider router = { router } />
createRoot ( document . getElementById ( 'root' ) ! ) . render ( < Routes /> ) 麻省理工学院