Rutas generadas basadas en archivos para VITE
Disfruté usando el enrutamiento basado en archivos desde que probé next.js (directorio de páginas). Después de aplicar el mismo concepto con aplicaciones VITE y del lado del cliente, comencé a escribir publicaciones de blog que cubren la implementación del enrutamiento basado en archivos del lado del cliente con React Router que se empaquetó más tarde como generouted .
Hoy generouted trae muchas características, admite múltiples marcos y enrutadores e inspira ideas y convenciones de Next.js, Remix, Expo, Docusaurus, Sveltekit y más.
generouted utiliza la API de importación del global de Vite para enumerar las rutas dentro del directorio src/pages y genera el árbol de rutas y los modales basados en las convenciones de generouted .
También hay complementos VITE disponibles para algunas integraciones para proporcionar componentes/ganchos/utilizos seguros a través de la generación de códigos.
react-router-dom o @tanstack/router ? o @tanstack/react-location@solidjs/router@mdx-js/rollup instalación y configuracióngenerouted a través de Stackblitzsrc/pages/ archivos y ver sus cambios reflejando En caso de que no tenga un proyecto VITE con React y TypeScript, consulte la documentación VITE para iniciar un nuevo proyecto.
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 /> ) Agregue la página de inicio creando un nuevo archivo src/pages/index.tsx → / , luego exporte un componente predeterminado:
export default function Home ( ) {
return < h1 > Home </ h1 >
}Verifique la sección de convenciones de enrutamiento a continuación.
Puede encontrar más detalles sobre la navegación tipo segura y los modales globales en @generouted/react-router docs.
En caso de que no tenga un proyecto VITE con sólido y mecanografiado, consulte la documentación VITE para iniciar un nuevo proyecto.
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' ) ! ) Agregue la página de inicio creando un nuevo archivo src/pages/index.tsx → / , luego exporte un componente predeterminado:
export default function Home ( ) {
return < h1 > Home </ h1 >
} Vea más sobre las convenciones de enrutamiento generouted a continuación.
Puede encontrar más detalles sobre la navegación tipo segura y los modales globales en los documentos de @generouted/solid-router .
Mira los documentos aquí
En caso de que no tenga un proyecto VITE con React y TypeScript, consulte la documentación VITE para iniciar un nuevo proyecto.
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 /> ) Agregue la página de inicio creando un nuevo archivo src/pages/index.tsx → / , luego exporte un componente predeterminado:
export default function Home ( ) {
return < h1 > Home </ h1 >
} src/pages.tsx , .jsx y .mdxsrc/pages/_app.tsx opcional para un diseño de nivel de aplicaciónsrc/pages/404.tsx opcional para una página no cubierta personalizada 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 en cualquier directorio anidado → src/pages/posts/_layout.tsx<Outlet /> para representar a los niños de diseñosrc/pages/posts/ En este caso se envolverán con ese diseño . entre los segmentos a convertir en barras hacia adelantesrc/pages/posts.nested.as.url.not.layout.tsx → /posts/nested/as/url/not/layout ()src/pages/(auth)/_layout.tsxsrc/pages/(auth)/login.tsx → /login+ (pensando que el modal es una ruta adicional que superpone la ruta actual)useModals()src/pages/+info.tsx → /infosrc/pages/+checkout/+details.tsx → /checkout/detailssrc/pages/+checkout/+payment.tsx → /checkout/payment - (pensando que el segmento puede restarse o eliminarse de la ruta de ruta)src/pages/-en/about.tsx → /en?/about → /en/about , /aboutsrc/pages/-[lang]/about.tsx → /:lang?/about → /en/about , /fr/about , /about _ se ignorará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| Archivo | Camino | Convención |
|---|---|---|
(auth)/_layout.tsx | Grupo de diseño sin senderos | |
(auth)/login.tsx | /login | Ruta regular |
(auth)/register.tsx | /register | Ruta regular |
blog/_components/button.tsx | Ruta ignorada por un directorio ignorado | |
blog/_components/comments.tsx | Ruta ignorada por un directorio ignorado | |
blog/[...all].tsx | /blog/* | Ruta dinámica de atrapar |
blog/[slug].tsx | /blog/:slug | Ruta dinámica |
blog/_layout.tsx | Diseño para /blog | |
blog/index.tsx | /blog | Ruta índice |
blog/tags.tsx | /blog/tags | Ruta regular |
docs/-[lang]/index.tsx | /docs/:lang?/index | Segmento de ruta dinámica opcional |
docs/-[lang]/resources.tsx | /docs/:lang?/resources | Segmento de ruta dinámica opcional |
docs/-en/contributors.tsx | /docs/en?/contributors | Segmento de ruta estática opcional |
+info.tsx | /info | Ruta modal |
404.tsx | * | Personalizado 404 (opcional) |
_app.tsx | Diseño de app personalizada (opcional) | |
_ignored.tsx | Ruta ignorada | |
about.tsx | /about | Ruta regular |
blog.wolayout.tsx | /blog/w/o/layout | Ruta sin /blog |
index.tsx | / | Ruta índice |
A través de @generouted/react-router o @generouted/solid-router
<Routes /> -El componente de enrutamiento basado en archivos se representará en la entrada de la aplicaciónroutes : árbol /objeto de rutas basadas en archivos utilizados por defecto en <Routes /> componente A través de @generouted/react-router/lazy o @generouted/solid-router/lazy
@generouted/react-router o @generouted/solid-router para habilitar la carga perezosasrc/pages/_app.tsx<Routes /> y las exportaciones routes A través de @generouted/react-router/plugin o @generouted/solid-router/plugin
src/router.ts<Link> , <Navigate> , useModals() , useNavigate() , useParams() , redirect() , etc.@generouted/react-router o @generouted/solid-router para obtener más detalles A través de @generouted/react-router/core o @generouted/solid-router/core
<Routes/>Hay múltiples enfoques para lograr eso. Si prefiere manejar la lógica en un solo lugar, puede definir las rutas protegidas con manejo de redirección dentro de un componente:
// 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
} Luego use ese componente ( <Redirects> ) en el diseño a nivel raíz src/pages/_app.tsx para envolver el componente <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 >
)
}Puede encontrar un ejemplo completo de este enfoque en la plantilla de render.
Puede usar el objeto routes exportadas para personalizar el enrutador o para usar enrutadores hash/memoria:
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 /> ) MIT