ДокументацияReactСоздание React приложения
Начальный 10 мин чтения

Создание React приложения

Как создать React-проект с нуля: Vite, структура папок, TypeScript, ESLint. Пошаговое руководство по настройке современного React-приложения.

ReactViteнастройка проектаструктураTypeScript

Способы создания React-проекта

Раньше все использовали Create React App (CRA). Сейчас он устарел — вместо него Vite или Next.js.

ИнструментДля чегоСборка
ViteSPA, лендинги, дашбордыДа (клиентская)
Next.jsSSR, SEO, крупные проектыСвой сервер
RemixSSR, progressive enhancementСвой сервер

Для большинства задач Vite — лучший старт.

Создание проекта через Vite

# С TypeScript
npm create vite@latest my-app -- --template react-ts

# С JavaScript
npm create vite@latest my-app -- --template react

# Или через yarn / pnpm / bun
yarn create vite my-app --template react-ts
pnpm create vite my-app --template react-ts
bunx create-vite my-app --template react-ts

Устанавливаем зависимости и запускаем:

cd my-app
npm install
npm run dev

Приложение будет доступно на http://localhost:5173.

Структура проекта

my-app/
├── public/             # Статические файлы (favicon, изображения)
│   └── vite.svg
├── src/
│   ├── assets/         # Файлы, которые обрабатывает сборщик
│   │   └── react.svg
│   ├── components/     # Переиспользуемые компоненты
│   │   ├── Button.tsx
│   │   └── Card.tsx
│   ├── hooks/          # Кастомные хуки
│   │   └── useWindowSize.ts
│   ├── pages/          # Страницы / views
│   │   ├── Home.tsx
│   │   └── About.tsx
│   ├── layouts/        # Шаблоны страниц
│   │   └── MainLayout.tsx
│   ├── services/       # API-клиенты, запросы
│   │   └── api.ts
│   ├── stores/         # Глобальное состояние (Zustand, Redux)
│   │   └── useCartStore.ts
│   ├── utils/          # Вспомогательные функции
│   │   └── format.ts
│   ├── types/          # TypeScript типы и интерфейсы
│   │   └── index.ts
│   ├── styles/         # Глобальные стили
│   │   └── globals.css
│   ├── App.tsx         # Корневой компонент
│   └── main.tsx        # Точка входа
├── index.html          # HTML-шаблон
├── package.json
├── tsconfig.json
├── vite.config.ts
└── .eslintrc.cjs

Vite не навязывает структуру — это один из возможных вариантов. Главное правило: группировать файлы по их роли.

Конфигурация Vite

Файл vite.config.ts:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  server: {
    port: 3000,
    open: true,
  },
  build: {
    outDir: 'dist',
    sourcemap: true,
  },
})

Алиас @ позволяет писать чистые импорты:

// Без алиаса
import { Button } from '../../../components/Button'

// С алиасом
import { Button } from '@/components/Button'

Чтобы TypeScript понимал алиас, добавьте в tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Точка входа

// src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
import './styles/globals.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

StrictMode включает дополнительные проверки в development-режиме: предупреждает об устаревших API и дважды вызывает рендер для обнаружения побочных эффектов.

Корневой компонент

// src/App.tsx
import { useState } from 'react'
import { Button } from '@/components/Button'

function App() {
  const [count, setCount] = useState(0)

  return (
    <div className="app">
      <h1>Привет, React + Vite!</h1>
      <Button onClick={() => setCount(c => c + 1)}>
        Кликнули {count} раз
      </Button>
    </div>
  )
}

export default App

Добавление роутинга

npm install react-router-dom
// src/App.tsx
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { MainLayout } from '@/layouts/MainLayout'
import { Home } from '@/pages/Home'
import { About } from '@/pages/About'

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={<MainLayout />}>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Route>
      </Routes>
    </BrowserRouter>
  )
}

CSS: подключение Tailwind

npm install -D tailwindcss @tailwindcss/vite

В vite.config.ts добавьте плагин:

import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [react(), tailwindcss()],
})

В src/styles/globals.css:

@import 'tailwindcss';

Всё, Tailwind работает — классы вроде bg-blue-500, text-white, p-4 доступны сразу.

Переменные окружения

Vite подхватывает переменные из .env-файлов с префиксом VITE_:

# .env.local
VITE_API_URL=http://localhost:4000/api
VITE_APP_TITLE=Мое приложение

Доступ в коде:

const apiUrl = import.meta.env.VITE_API_URL
const title = import.meta.env.VITE_APP_TITLE

Сборка для продакшена

npm run build

Vite соберёт проект в папку dist/. Результат можно проверить локально:

npm run preview

Проверка кода: ESLint + Prettier

npm install -D eslint @eslint/js typescript-eslint eslint-plugin-react-hooks eslint-plugin-react-refresh prettier eslint-config-prettier

Минимальный eslint.config.js:

import js from '@eslint/js'
import tseslint from 'typescript-eslint'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default tseslint.config(
  { ignores: ['dist'] },
  {
    extends: [js.configs.recommended, ...tseslint.configs.recommended],
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
    },
  },
)

Итог

Для старта React-проекта достаточно Vite — он быстрый, простой и гибкий. Базовый набор для комфортной разработки: Vite + TypeScript + ESLint + Tailwind. По мере роста проекта добавляются роутинг (react-router), менеджер состояния (Zustand) и работа с API (TanStack Query).