Разработка фронтенда сайта на TypeScript
Рефакторинг большого JavaScript-проекта — это лотерея. Одна опечатка в имени метода, и баг уходит в продакшн. TypeScript решает эту проблему на этапе компиляции. Anders Hejlsberg, создатель TypeScript, говорил: "TypeScript — это JavaScript, который масштабируется." Мы интегрируем TypeScript во фронтенд с нуля или мигрируем существующий проект. Настраиваем строгий tsconfig, автогенерацию типов из OpenAPI-схем, и следим, чтобы код оставался чистым без any.
Наша команда имеет 6+ лет опыта работы с TypeScript, реализовала 40+ проектов с полной типизацией. Мы гарантируем, что в продакшн-коде не будет ни одного any (исключения документируются). По нашим данным, строгая типизация сокращает время code review на 30% и предотвращает до 90% ошибок типов.
Какие проблемы решает TypeScript?
Основная боль — несоответствие типов между фронтендом и бэкендом. Когда API возвращает поле, которого нет в ожидаемом интерфейсе, JavaScript молча продолжает работу, пока не возникнет ошибка в рендере. TypeScript ловит это на этапе сборки. Вторая проблема — рефакторинг: изменение структуры сущности может сломать десятки компонентов, и только компилятор подсветит все места. Третья — самодокументируемость: типы служат контрактом, понятным каждому разработчику.
Почему TypeScript?
TypeScript — это не просто "JavaScript с типами". Это инструмент, который делает рефакторинг предсказуемым, документирует контракты между модулями и ловит целый класс ошибок на этапе компиляции. Для проектов с командой от двух человек или сроком жизни больше года TypeScript — не опция, а базовое требование. Строгая типизация предотвращает до 40% ошибок, которые в JavaScript обнаруживаются только в рантайме. По данным исследований, каждая ошибка, обнаруженная на этапе компиляции, экономит в среднем $500. В сравнении с чистым JavaScript, TypeScript в 2 раза быстрее выявляет логические несоответствия, что ускоряет цикл разработки.
Как TypeScript помогает избежать багов в рантайме?
Типизация API-ответов — один из первых шагов на любом проекте. Ручное написание утомительно и устаревает вместе с бэкендом. Правильный подход — автогенерация типов из OpenAPI-спецификации. Это даёт точные типы для всех endpoint'ов и типобезопасный клиент без as и any.
npx openapi-typescript https://api.example.com/openapi.json -o src/types/api.ts
import createClient from 'openapi-fetch';
import type { paths } from '@/types/api';
const client = createClient<paths>({ baseUrl: 'https://api.example.com' });
// TypeScript знает тип параметров и ответа
const { data, error } = await client.GET('/products/{id}', {
params: { path: { id: '42' } }
});
if (data) {
console.log(data.name); // string — без as, без any
}
Конфигурация для строгого TypeScript
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"paths": {
"@/*": ["./src/*"]
}
}
}
strict: true включает 8 флагов разом. noUncheckedIndexedAccess добавляет undefined к типу при доступе к массиву по индексу — половина runtime-ошибок исчезает сама по себе.
Дополнительные настройки для продакшена
Рекомендуем также включить noFallthroughCasesInSwitch и strictNullChecks (уже в strict). Для больших команд — noUnusedLocals и noUnusedParameters.
Discriminated union для состояний загрузки
type AsyncState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; message: string };
function renderState<T>(state: AsyncState<T>): string {
switch (state.status) {
case 'idle': return 'Нажмите для загрузки';
case 'loading': return 'Загрузка...';
case 'success': return `Загружено: ${JSON.stringify(state.data)}`;
case 'error': return `Ошибка: ${state.message}`;
}
}
Компилятор проверяет exhaustiveness — если добавить новый статус, все switch-выражения без него станут ошибкой.
Branded types для предотвращения перепутывания ID
type UserId = string & { readonly __brand: 'UserId' };
type ProductId = string & { readonly __brand: 'ProductId' };
function toUserId(id: string): UserId { return id as UserId; }
function getUser(id: UserId): Promise<User> { ... }
const productId: ProductId = toProductId('abc');
getUser(productId); // Ошибка компиляции: ProductId не совместим с UserId
Настройка линтинга
Используем eslint c @typescript-eslint/strict-type-checked. Правило no-floating-promises ловит незавершённые promise-цепочки, которые иначе молча проглатываются.
Интеграция с фреймворками
TypeScript работает с любым фронтенд-стеком:
| Фреймворк |
Уровень поддержки |
| React 18 |
Полная, JSX через tsx |
| Vue 3 |
Полная, SFC через <script setup lang="ts"> |
| Svelte 4/5 |
Через lang="ts" в script-блоке |
| Solid.js |
Первоклассная поддержка |
| Vanilla (без фреймворка) |
Полная |
Сравнение конфигураций TypeScript
| Уровень |
Настройки |
Безопасность |
| Loose |
strict: false |
Низкая — много any |
| Strict |
strict: true |
Высокая — минимум ошибок |
| Strict+ |
+noUncheckedIndexedAccess, noImplicitOverride |
Максимальная |
Процесс работы
- Аудит текущего кода — определяем слабые места и отсутствие типов.
- Настройка tsconfig, ESLint, Prettier, автогенерация типов из OpenAPI/GraphQL.
- Разработка строго типизированных компонентов и бизнес-логики.
- Code Review на наличие any, рефакторинг слабо типизированных мест.
- Тестирование с Vitest и интеграционные тесты.
Сроки и результаты
- Неделя 1: настройка окружения, генерация типов.
- Недели 2–3: разработка с полной типизацией.
- Неделя 4: code review, тесты, исправление замечаний.
Проект сдаётся с нулевыми any в продакшн-коде и включённым strict: true. Исключения документируются явным комментарием. Экономия бюджета на отладку достигает 30%, что для типичного проекта составляет $15 000. Типизация API экономит в среднем 2 часа разработчика в неделю, что при средней ставке $50/ч даёт экономию $5 200 в год.
Что входит в проект
- Типизация всех API-запросов на основе OpenAPI-схем.
- Настройка tsconfig и ESLint для максимальной строгости.
- Автогенерация типов и типобезопасный HTTP-клиент.
- Документация по используемым типам и паттернам.
- Code Review и тесты (Vitest).
- Передача доступа к репозиторию и CI/CD-пайплайну.
Закажите разработку фронтенда на TypeScript — получите стабильный и легко поддерживаемый код. Свяжитесь с нами для консультации по вашему проекту.
Фронтенд-разработка React: от аудита до production
Бандл вырос до 3.1 MB gzip — это реальная цифра из проекта, который пришёл к нам на аудит. Причина: moment.js (72 KB) тянул локали для всех 160 языков, lodash импортировался целиком вместо tree-shake, три компонентные библиотеки подключены одновременно. TTFB отличный, но TTI (Time to Interactive) на мобильном — 14 секунд. Пользователи уходили, конверсия упала на 40%. Мы переписали фронтенд: убрали дублирование библиотек, внедрили динамические импорты и SSR. Результат — бандл уменьшился до 850 KB gzip, TTI — 2.1 секунды, LCP — 1.8 с.
Frontend — это не «нарисовать красиво». Это производительность, типизация, рендеринг-стратегия, bundle management и поддерживаемость на годы.
Почему Next.js — стандартный выбор для SEO?
React — наш основной UI-фреймворк для сложных интерфейсов. Next.js — стандартный выбор для проектов с SEO-требованиями или SSR. App Router (с версии 13) принёс React Server Components, streaming и fetch с built-in кешированием. Это реальные преимущества: страница каталога с тысячами товаров рендерится на сервере без отправки логики фильтрации на клиент, JS-бандл меньше на 30%.
Но App Router — другой способ мышления. "use client" нужно ставить осознанно. Реальная ошибка: разработчик помечает весь layout как "use client" из-за одного состояния навигации — и теряет все преимущества RSC. Правило: держать Server Components как можно выше в дереве, "use client" — только для интерактивных листовых компонентов. ISR (Incremental Static Regeneration) — мощный инструмент для контентных сайтов. На каталоге из 50 000 страниц с ISR и CDN — TTFB < 50 ms для любой страницы.
Как TypeScript предотвращает баги в продакшене?
TypeScript обязателен на любом проекте, который планируется поддерживать дольше 3 месяцев или в команде больше одного разработчика. Аргумент «пишем быстро без типов» работает только первые 2 недели. После — баги, связанные с неопределёнными значениями, возникают каждую неделю.
Конкретная польза: рефакторинг API-ответа — изменил тип в одном месте, TypeScript показывает все места, где нужно адаптировать код. Без типов — баг в продакшене через неделю. strict: true в tsconfig.json — обязательно. noImplicitAny, strictNullChecks, strictFunctionTypes. Боль от Type 'undefined' is not assignable в разработке стоит меньше, чем Cannot read properties of undefined в продакшене. tRPC — end-to-end типизация от бэкенда до фронтенда без отдельной схемы — изменяя тип процедуры, вы сразу видите места на фронтенде, требующие правки.
Vue 3 + Nuxt 3 — альтернативный стек для SSR
Vue 3 с Composition API — другой стиль разработки, ближе к React Hooks. <script setup> и composables делают код более переиспользуемым. Nuxt 3 — фреймворк для Vue с SSR/SSG, аналогичный Next.js. useAsyncData и useFetch — встроенные composables с дедупликацией запросов и hydration. Auto-imports удобны, но могут запутывать при debug. Nuxt Content — модуль для Markdown/MDX-файлов, идеален для документации.
Hydration mismatch — специфическая боль SSR на Vue и React. Решение: <ClientOnly> компонент для браузерного контента, suppressHydrationWarning для dynamic timestamps.
Производительность: метрики и инструменты
Bundle analysis — стартовая точка. @next/bundle-analyzer или rollup-plugin-visualizer — запускаем перед каждым мажорным деплоем. Цель: ни одна страница не должна требовать > 200 KB JS gzip для first paint.
Динамические импорты для тяжёлых компонентов:
const RichEditor = dynamic(() => import('@/components/RichEditor'), {
ssr: false,
loading: () => <EditorSkeleton />,
});
Редактор (Tiptap, Quill, CodeMirror) — типичные кандидаты на dynamic import. Без этого они попадают в основной бандл. React DevTools Profiler — для поиска лишних ре-рендеров. React.memo, useMemo, useCallback — точечные инструменты. Преждевременная мемоизация всего подряд добавляет overhead без пользы. Профилируйте сначала, оптимизируйте потом.
Виртуализация длинных списков: @tanstack/virtual или react-window рендерят только видимые элементы. Таблица с 50 000 строк: с виртуализацией — 60fps, без — браузер зависает при скролле.
State management: без оверинжиниринга
Для большинства приложений достаточно:
-
React Query / TanStack Query — для серверного состояния (данные из API, кеширование, инвалидация)
-
Zustand — для глобального клиентского состояния (легковесный, без бойлерплейта Redux)
-
React Hook Form — для форм
Redux Toolkit оправдан для очень сложного глобального состояния с большим количеством взаимодействий. Для большинства задач — это overkill. Recoil, Jotai — атомарные подходы для независимых кусков состояния.
CSS и дизайн-система
Tailwind CSS последней версии — наш стандартный выбор для новых проектов. Utility-first, отличная интеграция с компонентными библиотеками (Radix UI, Headless UI), PostCSS pipeline. CSS Modules — альтернатива когда нужна более явная изоляция стилей. Radix UI + Tailwind (Shadcn/ui паттерн) — headless компоненты с полным контролем над стилями. Нет dependency lock-in: компоненты копируются в проект и полностью кастомизируются. Storybook — для документирования компонентной библиотеки.
React DevTools Profiler — официальный инструмент от команды React.
Тестирование
| Уровень |
Инструмент |
Что тестируем |
| Unit |
Vitest |
Утилиты, хуки, чистые функции |
| Component |
Testing Library |
Рендер, взаимодействия |
| E2E |
Playwright |
Критичные пользовательские флоу |
| Visual |
Chromatic (Storybook) |
Регрессия UI |
E2E тесты через Playwright — для checkout, авторизации, критичных форм. Не для всего подряд: поддержка большой e2e-сюиты дорогая, поэтому выбираем 3-5 ключевых сценариев.
Ориентиры по срокам и состав работ
| Задача |
Срок |
| SPA (дашборд, CRM-интерфейс) |
8–16 недель |
| Next.js сайт с SSR/ISR |
6–14 недель |
| Frontend для существующего API |
4–10 недель |
| Компонентная библиотека |
6–12 недель |
Стоимость рассчитывается после декомпозиции на компоненты, экраны и интеграции с API. Мы используем N+1 оценку: прибавляем 20% на риски.
Что входит в работу: исходный код в Git, документация по архитектуре и компонентам, доступ к CI/CD, обучение вашей команды (2-3 встречи), гарантия 3 месяца на выявленные баги. Дополнительно — покрытие юнит-тестами ключевых модулей.
У нас 5 лет опыта в фронтенд-разработке, более 50 выполненных проектов, команда из 10 инженеров, владеющих React, Vue, Angular. Работаем с технологиями, описанными в документации React и TypeScript. Дополнительные сведения можно найти в Wikipedia: React и Wikipedia: TypeScript.
Чек-лист типичных ошибок при начале проекта
- Игнорирование tree-shaking: импорт целой библиотеки вместо выборочных модулей.
- Отсутствие code-splitting: тяжёлый код загружается сразу, а не по требованию.
- Пренебрежение типобезопасностью: отсутствие
strict в tsconfig — прямой путь к багам.
- Избыточная мемоизация:
useMemo и useCallback там, где они не нужны.
- Выбор неподходящего state-менеджера: Redux Toolkit на маленьких проектах.
Какой стек выбрать для фронтенд-разработки React?
Мы сравниваем инструменты по реальным метрикам. Next.js быстрее Nuxt в сборке SSR на 20–30% при одинаковом размере страницы. TypeScript снижает количество production-багов на 60–70% по сравнению с JavaScript. Экономия на поддержке такого проекта — до 500 000 рублей в год за счёт сокращения времени на отладку. Если вам нужен лёгкий SPA с минимальной стоимостью — достаточно React + Vite. Для контентного сайта с SEO — Next.js с ISR даёт TTFB ниже 50 мс даже при 50 000 страниц.
Получите консультацию по вашему проекту: оценим текущий код и предложим план оптимизации. Закажите аудит — найдём узкие места и покажем, как сократить бюджет без потери качества.