w2b-vite-filebased-routing
v1.1.0
Published
🚀 Простой и мощный плагин для Vite с file-based routing
Maintainers
Readme
Vite File-Based Router
🚀 Простой и мощный плагин для Vite с file-based routing
Этот плагин предоставляет систему file-based routing для Vite приложений, вдохновленную Next.js. Он поддерживает страницы, лейауты, динамические маршруты, HMR, SEO оптимизацию и TypeScript.
✨ Особенности
- 🗂️ File-based routing - автоматическое создание маршрутов на основе файловой структуры
- 🏗️ Layout система - поддержка вложенных лейаутов
- 🔄 Hot Module Replacement - мгновенное обновление при изменении файлов
- 🎯 Динамические маршруты - поддержка
[id].tsx,[...slug].tsx - ⚡ Production оптимизация - code splitting, manifest генерация
- 🔧 TypeScript поддержка - полная типизация и автогенерация типов
- 📱 SEO оптимизация - автоматическая генерация метаданных, sitemap, robots.txt
- 🎨 JSX/TSX поддержка - работает с React компонентами
📦 Установка
npm install w2b-vite-filebased-routing
# или
pnpm add w2b-vite-filebased-routing
# или
yarn add w2b-vite-filebased-routing🚀 Быстрый старт
1. Настройка Vite
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { w2bViteFileBasedRouting } from 'w2b-vite-filebased-routing/core'
export default defineConfig({
plugins: [react(), w2bViteFileBasedRouting()],
})2. Создание структуры файлов
src/
├── pages/
│ ├── page.tsx # / (главная страница)
│ ├── about/
│ │ └── page.tsx # /about
│ ├── blog/
│ │ ├── page.tsx # /blog
│ │ ├── [id]/
│ │ │ └── page.tsx # /blog/[id]
│ │ └── [...slug]/
│ │ └── page.tsx # /blog/[...slug]
│ ├── layout.tsx # Root layout
│ └── (auth)/
│ ├── layout.tsx # Auth layout
│ └── login/
│ └── page.tsx # /login3. Создание страниц
// src/pages/page.tsx
/**
* @title Главная страница
* @description Добро пожаловать на наш сайт
* @keywords главная, добро пожаловать, сайт
* @changefreq daily
* @priority 1.0
*/
export default function HomePage() {
return (
<div>
<h1>Добро пожаловать!</h1>
<p>Это главная страница</p>
</div>
)
}
// Или через экспорт метаданных
export const metadata = {
title: 'Главная страница',
description: 'Добро пожаловать на наш сайт',
keywords: ['главная', 'добро пожаловать', 'сайт'],
changefreq: 'daily' as const,
priority: 1.0,
}4. Создание лейаутов
// src/pages/layout.tsx
interface LayoutProps {
children: React.ReactNode
}
export default function RootLayout({ children }: LayoutProps) {
return (
<div>
<header>
<nav>
<a href='/'>Главная</a>
<a href='/about'>О нас</a>
</nav>
</header>
<main>{children}</main>
<footer>
<p>© 2025 Мой сайт</p>
</footer>
</div>
)
}5. Динамические маршруты
// src/pages/blog/[id]/page.tsx
import { useParams } from 'react-router-dom'
export default function BlogPost() {
const { id } = useParams<{ id: string }>()
return (
<div>
<h1>Пост блога #{id}</h1>
<p>Содержимое поста...</p>
</div>
)
}
// Catch-all маршрут
// src/pages/docs/[...slug]/page.tsx
export default function DocsPage() {
const { slug } = useParams<{ slug: string[] }>()
return (
<div>
<h1>Документация: {slug?.join('/')}</h1>
</div>
)
}6. Подключение роутера в приложение
// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'w2b-vite-filebased-routing/react'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<RouterProvider />
</React.StrictMode>
)⚙️ Конфигурация
import { w2bViteFileBasedRouting } from 'w2b-vite-filebased-routing/core'
export default defineConfig({
plugins: [
w2bViteFileBasedRouting({
// 📁 Директория со страницами
pagesDir: 'src/pages',
// 📄 Имя файла страницы
pageFileName: 'page',
// 🏗️ Имя файла лейаута
layoutFileName: 'layout',
// 🎯 Расширения файлов для обработки
extensions: ['tsx', 'jsx'],
// 🌐 Базовый URL для SEO
baseUrl: 'https://example.com',
// 📍 Базовый путь для маршрутизации
// Используется для работы нескольких фронтендов на одном домене
basePath: '/', // '/' для основного сайта, '/admin' для админки
// 🚫 Пути для исключения из sitemap
disallowPaths: ['/admin', '/api', '/_internal'],
// 🔧 Генерировать TypeScript типы
generateTypes: true,
// 📱 Включить SEO оптимизацию
enableSEO: true,
}),
],
})🎯 Использование RouterProvider
import { RouterProvider } from 'w2b-vite-filebased-routing/react'
function App() {
return (
<RouterProvider preloader={<div>Загрузка...</div>}>
{/* Ваш контент */}
</RouterProvider>
)
}Переопределение basePath через пропсы
Вы можете переопределить basePath из конфигурации через пропсы:
import { RouterProvider } from 'w2b-vite-filebased-routing/react'
function App() {
return (
<RouterProvider basePath='/admin'>
{/* Админка будет работать на /admin/* */}
</RouterProvider>
)
}🌐 Работа нескольких фронтендов на одном домене
Плагин поддерживает работу нескольких фронтендов на одном домене с разными базовыми путями. Это полезно, когда у вас есть:
- Основной сайт на
/ - Админка на
/admin/ - Другое приложение на
/app/
Пример настройки для основного сайта
// vite.config.ts (основной сайт)
import { w2bViteFileBasedRouting } from 'w2b-vite-filebased-routing'
export default defineConfig({
plugins: [
w2bViteFileBasedRouting({
pagesDir: 'src/pages',
basePath: '/', // Основной сайт
}),
],
})Структура файлов:
src/pages/
├── page.tsx # https://domain.com/
├── about/
│ └── page.tsx # https://domain.com/about
└── map/
└── page.tsx # https://domain.com/mapПример настройки для админки
// vite.config.ts (админка)
import { w2bViteFileBasedRouting } from 'w2b-vite-filebased-routing'
export default defineConfig({
plugins: [
w2bViteFileBasedRouting({
pagesDir: 'src/admin/pages',
basePath: '/admin', // Админка на /admin/*
}),
],
})Структура файлов:
src/admin/pages/
├── page.tsx # https://domain.com/admin/
├── users/
│ └── page.tsx # https://domain.com/admin/users
└── map/
└── page.tsx # https://domain.com/admin/mapИспользование в приложении
// src/main.tsx (основной сайт)
import { RouterProvider } from 'w2b-vite-filebased-routing/react'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<RouterProvider />
</React.StrictMode>
)// src/admin/main.tsx (админка)
import { RouterProvider } from 'w2b-vite-filebased-routing/react'
ReactDOM.createRoot(document.getElementById('admin-root')!).render(
<React.StrictMode>
<RouterProvider basePath='/admin' />
</React.StrictMode>
)Важные замечания
- Разные директории страниц - каждый фронтенд должен иметь свою директорию
pagesDir - Разные точки входа - создайте отдельные
main.tsxфайлы для каждого фронтенда - Настройка Vite base - если используете Vite
baseопцию, убедитесь, что она совместима сbasePath - Навигация - используйте относительные пути или учитывайте
basePathпри навигации
🔄 HMR (Hot Module Replacement)
Плагин автоматически поддерживает HMR:
- ✅ Изменение страниц
- ✅ Изменение лейаутов
- ✅ Добавление новых маршрутов
- ✅ Удаление маршрутов
- ✅ Обновление виртуального модуля
⚡ Production оптимизация
Code Splitting (Разделение кода на чанки)
Плагин автоматически разделяет код на отдельные чанки для каждого маршрута и лейаута. Это означает:
- ✅ Каждая страница загружается отдельно - код страницы загружается только при переходе на соответствующий маршрут
- ✅ Лейауты загружаются независимо - каждый layout загружается как отдельный чанк
- ✅ Оптимизация размера бандла - пользователь загружает только необходимый код
- ✅ Автоматическая ленивая загрузка - используется
React.lazy()и динамические импортыimport()
Как это работает:
Динамические импорты - каждый маршрут генерируется с динамическим импортом:
loader: () => import('./pages/about/page.tsx')React.lazy() - компоненты оборачиваются в
React.lazy()для ленивой загрузки:const Page = React.lazy(async () => { const module = await loader() return module })React.Suspense - используется для отображения fallback во время загрузки:
<React.Suspense fallback={<div>Loading...</div>}> <Routes>{renderManifestAsRoutes(manifest)}</Routes> </React.Suspense>Vite автоматически создает чанки - при сборке Vite создает отдельные файлы для каждого динамического импорта:
dist/ ├── assets/ │ ├── index-[hash].js # Основной бандл │ ├── about-[hash].js # Чанк для /about │ ├── blog-[hash].js # Чанк для /blog │ └── blog-id-[hash].js # Чанк для /blog/[id]
Автоматические оптимизации
- Code splitting - автоматическое разделение кода по маршрутам
- Route manifest - манифест маршрутов для отладки
- TypeScript типы - автогенерация типов маршрутов
Генерируемые файлы
dist/
├── routes-manifest.js # Манифест маршрутов (для отладки)
├── sitemap.xml # Карта сайта
├── robots.txt # Robots.txt
└── types/
├── routes.d.ts # TypeScript типы маршрутов
└── metadata.d.ts # TypeScript типы метаданных📱 SEO оптимизация
Автоматическая генерация метаданных
Плагин автоматически извлекает метаданные из:
- JSDoc комментариев:
/**
* @title О нашей компании
* @description Узнайте больше о нашей компании
* @keywords компания, о нас, история
* @author Команда разработки
* @changefreq monthly
* @priority 0.8
*/
export default function AboutPage() {
return <h1>О нас</h1>
}- Экспорта метаданных:
export const metadata = {
title: 'О нас',
description: 'Узнайте больше о нашей компании',
keywords: ['компания', 'о нас', 'история'],
changefreq: 'monthly',
priority: 0.8,
}Генерируемые SEO файлы
- sitemap.xml - карта сайта для поисковых систем
- robots.txt - инструкции для поисковых роботов
- Метаданные - автоматическое извлечение из страниц
🔧 TypeScript поддержка
Автогенерация типов
Плагин автоматически генерирует TypeScript типы:
// dist/types/routes.d.ts
export type RoutePath =
| '/'
| '/about'
| '/blog'
| '/blog/[id]'
| '/docs/[...slug]'
export type RouteParams = {
'/blog/[id]': { id: string }
'/docs/[...slug]': { slug: string[] }
}
export type PageProps<T extends RoutePath = RoutePath> = {
params: RouteParams[T]
searchParams?: Record<string, string>
}
// Утилиты для навигации
export function navigate<T extends RoutePath>(
path: T,
params?: RouteParams[T]
): void
export function useParams<T extends RoutePath>(): RouteParams[T]Типы метаданных
// dist/types/metadata.d.ts
export interface PageMetadata {
title?: string
description?: string
keywords?: string[]
author?: string
changefreq?:
| 'always'
| 'hourly'
| 'daily'
| 'weekly'
| 'monthly'
| 'yearly'
| 'never'
priority?: number
}🧪 Тестирование функций
Проверка работы плагина
Запуск dev сервера:
npm run devПроверка маршрутов:
- Откройте браузер
- Перейдите по маршрутам
- Проверьте, что страницы загружаются
Проверка HMR:
- Измените файл страницы
- Убедитесь, что изменения отображаются без перезагрузки
Проверка production сборки
Сборка проекта:
npm run buildПроверка генерируемых файлов:
ls dist/ # Должны быть: routes-manifest.js, sitemap.xml, robots.txtЗапуск preview:
npm run previewПроверка маршрутов в production:
- Откройте браузер
- Перейдите по маршрутам
- Убедитесь, что все работает
Проверка SEO файлов
Проверка sitemap.xml:
cat dist/sitemap.xmlПроверка robots.txt:
cat dist/robots.txtПроверка в браузере:
- Откройте
http://localhost:4173/sitemap.xml - Откройте
http://localhost:4173/robots.txt
- Откройте
Проверка TypeScript типов
Проверка сгенерированных типов:
ls dist/types/ # Должны быть: routes.d.ts, metadata.d.tsПроверка в IDE:
- Откройте файл с импортом типов
- Убедитесь, что автодополнение работает
🐛 Решение проблем
Маршруты не создаются
- Проверьте
pagesDirв конфигурации - Убедитесь, что файлы имеют правильные расширения
- Проверьте консоль на ошибки
HMR не работает
- Убедитесь, что файлы находятся в
pagesDir - Проверьте, что файлы имеют поддерживаемые расширения
- Перезапустите dev сервер
TypeScript ошибки
- Установите типы:
npm install @types/react @types/react-dom - Проверьте
tsconfig.json - Убедитесь, что импортируете типы правильно
📊 Производительность
Оптимизации
- Ленивая загрузка компонентов - компоненты загружаются только при необходимости
- Code splitting по маршрутам - автоматическое разделение кода по маршрутам
- Кэширование парсинга файлов - ускорение повторного сканирования
- Виртуальные модули - быстрая загрузка манифеста маршрутов
- HMR оптимизация - мгновенное обновление при изменении файлов
- Production manifest - предварительно сгенерированный манифест для production
Лицензия
MIT © da-b1rmuda
Создано с ❤️ для Web2Bizz
