Сгенерированные маршруты на основе файлов для VITE
Мне нравилось использовать маршрутизацию на основе файлов с тех пор, как я попробовал next.js (каталог страниц). После применения той же концепции с приложениями VITE и клиентами я начал писать сообщения в блогах, охватывающие реализацию маршрутизации на основе файлов на стороне клиента с помощью маршрутизатора React, который был упакован позже в качестве generouted .
Сегодня generouted приносит много функций, поддерживает несколько рамок и маршрутизаторов, а также вдохновляет идеи и соглашения от Next.js, Remix, Expo, Docusaurus, Sveltekit и других.
generouted использует API Import VITE Glob для перечисления маршрутов в каталоге src/pages и генерирует дерева и модалы маршрутов на основе конвенций generouted .
Существуют также плагины VITE, доступные для некоторых интеграций, чтобы предоставить типовые компоненты/крючки/UTILS с помощью генерации кода.
react-router-dom или @tanstack/router ? или @tanstack/react-location@solidjs/router@mdx-js/rollupgenerouted через Stackblitzsrc/pages/ Files и смотрите ваши изменения, отражающие Если у вас нет проекта Vite с React и TypeScript, проверьте документацию 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 Docs.
Если у вас нет проекта 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 Docs.
Проверьте документы здесь
Если у вас нет проекта Vite с React и TypeScript, проверьте документацию 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/ Directory в этом случае будут обернуты с этим макетом . Между сегментами, которые будут преобразованы в прямое удары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 /> Component Через @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 Docs или @generouted/solid-router для получения более подробной информации Через @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
} Затем используйте этот компонент ( <Redirects> ) на макете уровня корня src/pages/_app.tsx чтобы обернуть компонент <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 /> ) Грань