379 lines
11 KiB
Markdown
379 lines
11 KiB
Markdown
# Миграция с React 18 на SolidStart: Comprehensive Guide
|
||
|
||
## 1. Введение
|
||
|
||
### 1.1 Что такое SolidStart?
|
||
|
||
SolidStart - это метафреймворк для SolidJS, который предоставляет полнофункциональное решение для создания веб-приложений. Ключевые особенности:
|
||
|
||
- Полностью изоморфное приложение (работает на клиенте и сервере)
|
||
- Встроенная поддержка SSR, SSG и CSR
|
||
- Интеграция с Vite и Nitro
|
||
- Гибкая маршрутизация
|
||
- Встроенные серверные функции и действия
|
||
|
||
### 1.2 Основные различия между React и SolidStart
|
||
|
||
| Характеристика | React 18 | SolidStart |
|
||
|---------------|----------|------------|
|
||
| Рендеринг | Virtual DOM | Компиляция и прямое обновление DOM |
|
||
| Серверный рендеринг | Сложная настройка | Встроенная поддержка |
|
||
| Размер бандла | ~40 кБ | ~7.7 кБ |
|
||
| Реактивность | Хуки с зависимостями | Сигналы без явных зависимостей |
|
||
| Маршрутизация | react-router | @solidjs/router |
|
||
|
||
## 2. Подготовка проекта
|
||
|
||
### 2.1 Установка зависимостей
|
||
|
||
```bash
|
||
# Удаление React зависимостей
|
||
npm uninstall react react-dom react-router-dom
|
||
|
||
# Установка SolidStart и связанных библиотек
|
||
npm install @solidjs/start solid-js @solidjs/router
|
||
```
|
||
|
||
### 2.2 Обновление конфигурации
|
||
|
||
#### Vite Configuration (`vite.config.ts`)
|
||
```typescript
|
||
import { defineConfig } from 'vite';
|
||
import solid from 'solid-start/vite';
|
||
|
||
export default defineConfig({
|
||
plugins: [solid()],
|
||
// Дополнительные настройки
|
||
});
|
||
```
|
||
|
||
#### TypeScript Configuration (`tsconfig.json`)
|
||
```json
|
||
{
|
||
"compilerOptions": {
|
||
"jsx": "preserve",
|
||
"jsxImportSource": "solid-js",
|
||
"types": ["solid-start/env"]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### SolidStart Configuration (`app.config.ts`)
|
||
```typescript
|
||
import { defineConfig } from "@solidjs/start/config";
|
||
|
||
export default defineConfig({
|
||
server: {
|
||
// Настройки сервера, например:
|
||
preset: "netlify" // или другой провайдер
|
||
},
|
||
// Дополнительные настройки
|
||
});
|
||
```
|
||
|
||
## 3. Миграция компонентов и логики
|
||
|
||
### 3.1 Состояние и реактивность
|
||
|
||
#### React:
|
||
```typescript
|
||
const [count, setCount] = useState(0);
|
||
```
|
||
|
||
#### SolidJS:
|
||
```typescript
|
||
const [count, setCount] = createSignal(0);
|
||
// Использование: count(), setCount(newValue)
|
||
```
|
||
|
||
### 3.2 Серверные функции и загрузка данных
|
||
|
||
В SolidStart есть несколько способов работы с данными:
|
||
|
||
#### Серверная функция
|
||
```typescript
|
||
// server/api.ts
|
||
export function getUser(id: string) {
|
||
return db.users.findUnique({ where: { id } });
|
||
}
|
||
|
||
// Component
|
||
export default function UserProfile() {
|
||
const user = createAsync(() => getUser(params.id));
|
||
|
||
return <div>{user()?.name}</div>;
|
||
}
|
||
```
|
||
|
||
#### Действия (Actions)
|
||
```typescript
|
||
export function updateProfile(formData: FormData) {
|
||
'use server';
|
||
const name = formData.get('name');
|
||
// Логика обновления профиля
|
||
}
|
||
```
|
||
|
||
### 3.3 Маршрутизация
|
||
|
||
```typescript
|
||
// src/routes/index.tsx
|
||
import { A } from "@solidjs/router";
|
||
|
||
export default function HomePage() {
|
||
return (
|
||
<div>
|
||
<A href="/about">О нас</A>
|
||
<A href="/profile">Профиль</A>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// src/routes/profile.tsx
|
||
export default function ProfilePage() {
|
||
return <div>Профиль пользователя</div>;
|
||
}
|
||
```
|
||
|
||
## 4. Оптимизация и производительность
|
||
|
||
### 4.1 Мемоизация
|
||
|
||
```typescript
|
||
// Кэширование сложных вычислений
|
||
const sortedUsers = createMemo(() =>
|
||
users().sort((a, b) => a.name.localeCompare(b.name))
|
||
);
|
||
|
||
// Ленивая загрузка
|
||
const UserList = lazy(() => import('./UserList'));
|
||
```
|
||
|
||
### 4.2 Серверный рендеринг и предзагрузка
|
||
|
||
```typescript
|
||
// Предзагрузка данных
|
||
export function routeData() {
|
||
return {
|
||
user: createAsync(() => fetchUser())
|
||
};
|
||
}
|
||
|
||
export default function UserPage() {
|
||
const user = useRouteData<typeof routeData>();
|
||
return <div>{user().name}</div>;
|
||
}
|
||
```
|
||
|
||
## 5. Особенности миграции
|
||
|
||
### 5.1 Ключевые изменения
|
||
- Замена `useState` на `createSignal`
|
||
- Использование `createAsync` вместо `useEffect` для загрузки данных
|
||
- Серверные функции с `'use server'`
|
||
- Маршрутизация через `@solidjs/router`
|
||
|
||
### 5.2 Потенциальные проблемы
|
||
- Переписать все React-специфичные хуки
|
||
- Адаптировать библиотеки компонентов
|
||
- Обновить тесты и CI/CD
|
||
|
||
## 6. Деплой
|
||
|
||
SolidStart поддерживает множество платформ:
|
||
- Netlify
|
||
- Vercel
|
||
- Cloudflare
|
||
- AWS
|
||
- Deno
|
||
- и другие
|
||
|
||
```typescript
|
||
// app.config.ts
|
||
export default defineConfig({
|
||
server: {
|
||
preset: "netlify" // Выберите вашу платформу
|
||
}
|
||
});
|
||
```
|
||
|
||
## 7. Инструменты и экосистема
|
||
|
||
### Рекомендованные библиотеки
|
||
- Роутинг: `@solidjs/router`
|
||
- Состояние: Встроенные примитивы SolidJS
|
||
- Запросы: `@tanstack/solid-query`
|
||
- Девтулзы: `solid-devtools`
|
||
|
||
## 8. Миграция конкретных компонентов
|
||
|
||
### 8.1 Страница регистрации (RegisterPage)
|
||
|
||
#### React-версия
|
||
```typescript
|
||
import React from 'react'
|
||
import { Navigate } from 'react-router-dom'
|
||
import { RegisterForm } from '../components/auth/RegisterForm'
|
||
import { useAuthStore } from '../store/authStore'
|
||
|
||
export const RegisterPage: React.FC = () => {
|
||
const { isAuthenticated } = useAuthStore()
|
||
|
||
if (isAuthenticated) {
|
||
return <Navigate to="/" replace />
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen ...">
|
||
<RegisterForm />
|
||
</div>
|
||
)
|
||
}
|
||
```
|
||
|
||
#### SolidJS-версия
|
||
```typescript
|
||
import { Navigate } from '@solidjs/router'
|
||
import { Show } from 'solid-js'
|
||
import { RegisterForm } from '../components/auth/RegisterForm'
|
||
import { useAuthStore } from '../store/authStore'
|
||
|
||
export default function RegisterPage() {
|
||
const { isAuthenticated } = useAuthStore()
|
||
|
||
return (
|
||
<Show when={!isAuthenticated()} fallback={<Navigate href="/" />}>
|
||
<div class="min-h-screen ...">
|
||
<RegisterForm />
|
||
</div>
|
||
</Show>
|
||
)
|
||
}
|
||
```
|
||
|
||
#### Ключевые изменения
|
||
- Удаление импорта React
|
||
- Использование `@solidjs/router` вместо `react-router-dom`
|
||
- Замена `className` на `class`
|
||
- Использование `Show` для условного рендеринга
|
||
- Вызов `isAuthenticated()` как функции
|
||
- Использование `href` вместо `to`
|
||
- Экспорт по умолчанию вместо именованного экспорта
|
||
|
||
### Рекомендации
|
||
- Всегда используйте `Show` для условного рендеринга
|
||
- Помните, что сигналы в SolidJS - это функции
|
||
- Следите за совместимостью импортов и маршрутизации
|
||
|
||
## 9. UI Component Migration
|
||
|
||
### 9.1 Key Differences in Component Structure
|
||
|
||
When migrating UI components from React to SolidJS, several key changes are necessary:
|
||
|
||
1. **Props Handling**
|
||
- Replace `React.FC<Props>` with function component syntax
|
||
- Use object destructuring for props instead of individual parameters
|
||
- Replace `className` with `class`
|
||
- Use `props.children` instead of `children` prop
|
||
|
||
2. **Type Annotations**
|
||
- Use TypeScript interfaces for props
|
||
- Explicitly type `children` as `any` or a more specific type
|
||
- Remove React-specific type imports
|
||
|
||
3. **Event Handling**
|
||
- Use SolidJS event types (e.g., `InputEvent`)
|
||
- Modify event handler signatures to match SolidJS conventions
|
||
|
||
### 9.2 Component Migration Example
|
||
|
||
#### React Component
|
||
```typescript
|
||
import React from 'react'
|
||
import { clsx } from 'clsx'
|
||
|
||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||
variant?: 'primary' | 'secondary'
|
||
fullWidth?: boolean
|
||
}
|
||
|
||
export const Button: React.FC<ButtonProps> = ({
|
||
variant = 'primary',
|
||
fullWidth = false,
|
||
className,
|
||
children,
|
||
...props
|
||
}) => {
|
||
const classes = clsx(
|
||
'button',
|
||
variant === 'primary' && 'bg-blue-500',
|
||
fullWidth && 'w-full',
|
||
className
|
||
)
|
||
|
||
return (
|
||
<button className={classes} {...props}>
|
||
{children}
|
||
</button>
|
||
)
|
||
}
|
||
```
|
||
|
||
#### SolidJS Component
|
||
```typescript
|
||
import { clsx } from 'clsx'
|
||
|
||
interface ButtonProps {
|
||
variant?: 'primary' | 'secondary'
|
||
fullWidth?: boolean
|
||
class?: string
|
||
children: any
|
||
disabled?: boolean
|
||
type?: 'button' | 'submit'
|
||
onClick?: () => void
|
||
}
|
||
|
||
export const Button = (props: ButtonProps) => {
|
||
const classes = clsx(
|
||
'button',
|
||
props.variant === 'primary' && 'bg-blue-500',
|
||
props.fullWidth && 'w-full',
|
||
props.class
|
||
)
|
||
|
||
return (
|
||
<button
|
||
class={classes}
|
||
disabled={props.disabled}
|
||
type={props.type || 'button'}
|
||
onClick={props.onClick}
|
||
>
|
||
{props.children}
|
||
</button>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 9.3 Key Migration Strategies
|
||
|
||
- Replace `React.FC` with standard function components
|
||
- Use `props` object instead of individual parameters
|
||
- Replace `className` with `class`
|
||
- Modify event handling to match SolidJS patterns
|
||
- Remove React-specific lifecycle methods
|
||
- Use SolidJS primitives like `createEffect` for side effects
|
||
|
||
## Заключение
|
||
|
||
Миграция на SolidStart требует внимательного подхода, но предоставляет значительные преимущества в производительности, простоте разработки и серверных возможностях.
|
||
|
||
### Рекомендации
|
||
- Мигрируйте постепенно
|
||
- Пишите тесты на каждом этапе
|
||
- Используйте инструменты совместимости
|
||
|
||
---
|
||
|
||
Этот гайд поможет вам систематически и безопасно мигрировать ваш проект на SolidStart, сохраняя существующую функциональность и улучшая производительность.
|