Des itinéraires basés sur des fichiers pour VITE
J'ai aimé utiliser le routage basé sur les fichiers depuis que j'ai essayé Next.js (répertoire des pages). Après avoir appliqué le même concept avec des applications VITE et côté client, j'ai commencé à écrire des articles de blog couvrant la mise en œuvre du routage basé sur les fichiers côté client avec le routeur React qui a été emballé plus tard comme generouted .
Aujourd'hui, generouted apporte de nombreuses fonctionnalités, prend en charge plusieurs frameworks et routeurs, et inspire les idées et les conventions de Next.js, Remix, Expo, Docusaurus, Sveltekit et plus encore.
generouted utilise l'API Glob Import de Vite pour répertorier les routes dans le répertoire src/pages et génère l'arborescence des routes et les modaux en fonction des conventions generouted .
Il existe également des plugins VITE disponibles pour certaines intégrations pour fournir des composants / crochets / utils de type type via la génération de code.
react-router-dom ou @tanstack/router ? ou @tanstack/react-location@solidjs/router@mdx-js/rollupgenerouted via Stackblitzsrc/pages/ fichiers et voir vos modifications reflétant Dans le cas où vous n'avez pas de projet VITE avec React et TypeScript, consultez la documentation VITE pour démarrer un nouveau projet.
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 /> ) Ajoutez la page d'accueil en créant un nouveau fichier src/pages/index.tsx → / , puis exportez un composant par défaut:
export default function Home ( ) {
return < h1 > Home </ h1 >
}Vérifiez la section des conventions de routage ci-dessous.
Vous pouvez trouver plus de détails sur la navigation de type type et les modaux mondiaux chez @generouted/react-router .
Dans le cas où vous n'avez pas de projet VITE avec Solid et TypeScript, consultez la documentation VITE pour démarrer un nouveau projet.
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' ) ! ) Ajoutez la page d'accueil en créant un nouveau fichier src/pages/index.tsx → / , puis exportez un composant par défaut:
export default function Home ( ) {
return < h1 > Home </ h1 >
} En savoir plus sur les conventions de routage generouted ci-dessous.
Vous pouvez trouver plus de détails sur la navigation de type type et les modaux mondiaux chez @generouted/solid-router .
Découvrez les documents ici
Dans le cas où vous n'avez pas de projet VITE avec React et TypeScript, consultez la documentation VITE pour démarrer un nouveau projet.
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 /> ) Ajoutez la page d'accueil en créant un nouveau fichier src/pages/index.tsx → / , puis exportez un composant par défaut:
export default function Home ( ) {
return < h1 > Home </ h1 >
} src/pages.tsx , .jsx et .mdxsrc/pages/_app.tsx pour une disposition au niveau de l'applicationsrc/pages/404.tsx pour une page de non-fond personnalisée 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 dans n'importe quel répertoire imbriqué → src/pages/posts/_layout.tsx<Outlet /> pour rendre les enfants de mise en pagesrc/pages/posts/ répertoire dans ce cas seront enveloppés de cette mise en page . Entre les segments à convertir en barres tronquéessrc/pages/posts.nested.as.url.not.layout.tsx → /posts/nested/as/url/not/layout ()src/pages/(auth)/_layout.tsxsrc/pages/(auth)/login.tsx → /login+ pensant que le modal est un itinéraire supplémentaire superposant l'itinéraire actuel)useModals()src/pages/+info.tsx → /infosrc/pages/+checkout/+details.tsx → /checkout/detailssrc/pages/+checkout/+payment.tsx → /checkout/payment - (pensant que le segment peut être soustrait ou supprimé du chemin de la route)src/pages/-en/about.tsx → /en?/about → /en/about , /aboutsrc/pages/-[lang]/about.tsx → /:lang?/about → /en/about , /fr/about , /about _ sera ignoré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| Déposer | Chemin | Convention |
|---|---|---|
(auth)/_layout.tsx | Groupe de mise en page sans chemin | |
(auth)/login.tsx | /login | Voie régulière |
(auth)/register.tsx | /register | Voie régulière |
blog/_components/button.tsx | Route ignorée par un répertoire ignoré | |
blog/_components/comments.tsx | Route ignorée par un répertoire ignoré | |
blog/[...all].tsx | /blog/* | Route de fourre-tout dynamique |
blog/[slug].tsx | /blog/:slug | Voie dynamique |
blog/_layout.tsx | Disposition pour les routes /blog | |
blog/index.tsx | /blog | Voie d'indexation |
blog/tags.tsx | /blog/tags | Voie régulière |
docs/-[lang]/index.tsx | /docs/:lang?/index | Segment d'itinéraire dynamique en option |
docs/-[lang]/resources.tsx | /docs/:lang?/resources | Segment d'itinéraire dynamique en option |
docs/-en/contributors.tsx | /docs/en?/contributors | Segment d'itinéraire statique en option |
+info.tsx | /info | Voie modale |
404.tsx | * | Custom 404 (facultatif) |
_app.tsx | Disposition app personnalisée (facultative) | |
_ignored.tsx | Route ignorée | |
about.tsx | /about | Voie régulière |
blog.wolayout.tsx | /blog/w/o/layout | Route sans /blog |
index.tsx | / | Voie d'indexation |
Via @generouted/react-router ou @generouted/solid-router
<Routes /> - Composant de routage basé sur des fichiers à rendre dans l'entrée de l'applicationroutes - arborescence / objet basés sur des fichiers utilisés par défaut au composant <Routes /> Via @generouted/react-router/lazy ou @generouted/solid-router/lazy
@generouted/react-router ou @generouted/solid-router pour permettre le chargement paresseuxsrc/pages/_app.tsx<Routes /> et les exportations routes Via @generouted/react-router/plugin ou @generouted/solid-router/plugin
src/router.ts<Link> , <Navigate> , useModals() , useNavigate() , useParams() , redirect() , etc.@generouted/react-router ou les documents @generouted/solid-router pour plus de détails Via @generouted/react-router/core ou @generouted/solid-router/core
<Routes/>Il existe plusieurs approches pour y parvenir. Si vous préférez la manipulation de la logique en un seul endroit, vous pouvez définir les itinéraires protégés avec une manipulation de redirection dans un composant:
// 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
} Ensuite, utilisez ce composant ( <Redirects> ) au niveau de la disposition du niveau racine src/pages/_app.tsx Pour envelopper le composant <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 >
)
}Vous pouvez trouver un exemple complet de cette approche sur le modèle de rendu
Vous pouvez utiliser l'objet routes exporté pour personnaliser le routeur ou pour utiliser des routeurs de hachage / mémoire:
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