Rotas baseadas em arquivos geradas para vite
Gostei de usar o roteamento baseado em arquivos desde que tentei o próximo.js (diretório de páginas). Depois de aplicar o mesmo conceito com aplicativos Vite e do lado do cliente, comecei a escrever postagens no blog, cobrindo a implementação do roteamento baseado em arquivos do lado do cliente com o Router React, que foi embalado posteriormente conforme generouted .
Hoje, generouted traz muitos recursos, suporta várias estruturas e roteadores e inspira idéias e convenções de Next.js, Remix, Expo, Docusaurus, Sveltekit e muito mais.
generouted usa a API de importação global da Vite para listar as rotas no diretório src/pages e gera a árvore de rotas e os modais com base nas convenções de generouted .
Também existem plug-ins de vite disponíveis para algumas integrações para fornecer componentes/ganchos/utils seguros de tipo por meio de geração de código.
react-router-dom ou @tanstack/router ? ou @tanstack/react-location@solidjs/router@mdx-js/rollup instalação e configuraçãogenerouted via Stackblitzsrc/pages/ arquivos e veja suas alterações refletindo Caso você não tenha um projeto Vite com React e TypeScript, verifique a documentação do Vite para iniciar um novo projeto.
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 /> ) Adicione a página inicial criando um novo arquivo src/pages/index.tsx → / e, em seguida, exporte um componente padrão:
export default function Home ( ) {
return < h1 > Home </ h1 >
}Verifique a seção Convenções de roteamento abaixo.
Você pode encontrar mais detalhes sobre a navegação por tipo de tipo e os modais globais nos documentos @generouted/react-router .
Caso você não tenha um projeto vite com sólido e digital, verifique a documentação do Vite para iniciar um novo projeto.
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' ) ! ) Adicione a página inicial criando um novo arquivo src/pages/index.tsx → / e, em seguida, exporte um componente padrão:
export default function Home ( ) {
return < h1 > Home </ h1 >
} Veja mais sobre convenções de roteamento generouted abaixo.
Você pode encontrar mais detalhes sobre a navegação por tipo de tipo e os modais globais nos documentos de @generouted/solid-router .
Confira os documentos aqui
Caso você não tenha um projeto Vite com React e TypeScript, verifique a documentação do Vite para iniciar um novo projeto.
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 /> ) Adicione a página inicial criando um novo arquivo src/pages/index.tsx → / e, em seguida, exporte um componente padrão:
export default function Home ( ) {
return < h1 > Home </ h1 >
} src/pages.tsx , .jsx e .mdxsrc/pages/_app.tsx para um layout de nível de aplicativosrc/pages/404.tsx para uma página personalizada não encontrada 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 em qualquer diretório aninhado → src/pages/posts/_layout.tsx<Outlet /> para renderizar crianças de layoutsrc/pages/posts/ Diretório neste caso serão envolvidos com esse layout . entre os segmentos a serem convertidos em barras para a frentesrc/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 o modal é uma rota extra sobrepondo a rota atual)useModals()src/pages/+info.tsx → /infosrc/pages/+checkout/+details.tsx → /checkout/detailssrc/pages/+checkout/+payment.tsx → /checkout/payment - (pensando que o segmento pode ser subtraído ou removido do caminho da rota)src/pages/-en/about.tsx → /en?/about → /en/about , /aboutsrc/pages/-[lang]/about.tsx → /:lang?/about /en/about , /fr/about , /about _ será ignoradosrc/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| Arquivo | Caminho | Convenção |
|---|---|---|
(auth)/_layout.tsx | Grupo de layout sem caminho | |
(auth)/login.tsx | /login | Rota regular |
(auth)/register.tsx | /register | Rota regular |
blog/_components/button.tsx | Rota ignorada por um diretório ignorado | |
blog/_components/comments.tsx | Rota ignorada por um diretório ignorado | |
blog/[...all].tsx | /blog/* | Rota dinâmica de captura |
blog/[slug].tsx | /blog/:slug | Rota dinâmica |
blog/_layout.tsx | Layout para rotas /blog | |
blog/index.tsx | /blog | Rota de índice |
blog/tags.tsx | /blog/tags | Rota regular |
docs/-[lang]/index.tsx | /docs/:lang?/index | Segmento de rota dinâmica opcional |
docs/-[lang]/resources.tsx | /docs/:lang?/resources | Segmento de rota dinâmica opcional |
docs/-en/contributors.tsx | /docs/en?/contributors | Segmento de rota estática opcional |
+info.tsx | /info | Rota modal |
404.tsx | * | 404 personalizado (opcional) |
_app.tsx | Layout app personalizado (opcional) | |
_ignored.tsx | Rota ignorada | |
about.tsx | /about | Rota regular |
blog.wolayout.tsx | /blog/w/o/layout | Rota sem /blog |
index.tsx | / | Rota de índice |
Via @generouted/react-router ou @generouted/solid-router
<Routes /> -Componente de roteamento baseado em arquivos a ser renderizado na entrada do aplicativoroutes -rotas baseadas em arquivos Árvore /objeto usado por padrão em <Routes /> componente Via @generouted/react-router/lazy ou @generouted/solid-router/lazy
@generouted/react-router ou @generouted/solid-router para ativar o carregamento preguiçososrc/pages/_app.tsx<Routes /> e as exportações 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 @generouted/solid-router documentos para obter mais detalhes Via @generouted/react-router/core ou @generouted/solid-router/core
<Routes/>Existem várias abordagens para conseguir isso. Se você preferir lidar com a lógica em um só lugar, pode definir as rotas protegidas com o manuseio de redirecionamento dentro de um 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
} Em seguida, use esse componente ( <Redirects> ) no layout do nível da raiz src/pages/_app.tsx para embrulhar o 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 >
)
}Você pode encontrar um exemplo completo dessa abordagem no modelo de renderização
Você pode usar o objeto de routes exportadas para personalizar o roteador ou usar roteadores de hash/memória:
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