Программа учебника
На примере Atmanki изучаем JavaScript и TypeScript, React, Next.js, управление состоянием, API, Strapi и развёртывание. Сквозной проект — сайт «Атмановских кулачек»: от преобразования данных и компонентов до публикации контента и релиза на VPS. В интерфейсе используются Mantine и собственный UIKit, для контрактов — Zod и tRPC, для хранения — PostgreSQL и Garage S3.
Читать онлайн · Запустить проект
Для кого написан учебник
Предполагаем математический бэкграунд: множества и отображения, логика, отношения, графы, индукция и базовое понимание сложности алгоритмов. Опыт JavaScript, React или эксплуатации серверов при этом не обязателен. Перед векторным поиском кратко освежаем линейную алгебру, перед оценкой качества и задержек — вероятность и статистику. Знание теории категорий не требуется.
Объяснения связывают модель, её свойства и исполняемый пример:
- Типы — множества допустимых значений; объект — произведение, tagged union — размеченная сумма. Отдельно рассматриваем ограничения этой модели для TypeScript.
- Валидация — проверка предиката и разбор внешнего значения в модель приложения; преобразование и ошибка разбора описываются явно.
- Чистая функция — отображение с явным входом; композиция и законы проверяются на примерах, побочные эффекты рассматриваются отдельно.
- Переход состояния —
step: State × Event → State; для недопустимых событий явно выбираем отказ, отсутствие изменения или отдельный результат перехода. - Реактивность — зависимости и значения во времени; сравниваем дискретные события и модель сигнала, прежде чем связывать понятия с библиотеками.
- Распределённая агрегация — объединение частичных результатов; проверяем ассоциативность, нейтральный элемент и условия перестановки.
- Идемпотентность —
f(f(s)) = f(s)для фиксированной операции и моделируемого эффекта. Эта формула не утверждает одинаковых ответов или однократной доставки.
Математическая модель сопровождается областью применимости и контрпримером: числа JavaScript не являются точной вещественной арифметикой, сеть может потерять ответ, а типы не выполняют проверку HTTP-данных во время работы программы.
Как пользоваться учебником
Ниже — последовательная программа написанного учебника: основы, разбор Atmanki и лаборатории. Все части имеют материалы и критерии самостоятельной проверки. Готовый текст лаборатории не означает, что её внешние сервисы уже испытаны: границы проверки отделяют выполненные примеры от ручных браузерных и инфраструктурных опытов.
Читайте части по порядку, если осваиваете стек впервые. Если знаете основы, переходите к нужной части и сверяйтесь с её входными требованиями. Команды выполняются из корня репозитория, если явно не указан другой каталог. Документация описывает код; наличие инструкции не подтверждает публикацию изменения или его проверку на живом сайте.
Устройство учебной главы
Каждая новая или переработанная глава следует одному порядку:
- Задача и знания, которые нужны для её решения.
- Понятие, математическая модель, небольшая схема, её границы и типичная ошибка.
- Применение в Atmanki со ссылкой на исходный код.
- Самостоятельное изменение на локальных учебных данных.
- Проверка результата и вопросы для объяснения своими словами.
Проверки вводятся вместе с примерами с самого начала; отдельная часть о качестве позже систематизирует инструменты. Учебный пример, упражнение и реализованное поведение приложения всегда обозначаются отдельно.
Схемы как часть объяснения
Схема отвечает на один вопрос и дополняется пояснением: что означают узлы, стрелки, состояния и границы. Для сложной темы используем несколько небольших схем: общая модель → конкретный сценарий → отказ или контрпример. Один рисунок не должен смешивать зависимости кода, движение данных и время.
Ниже — карта роли иллюстраций в частях учебника. Схемы встроены в главы; Mermaid поддерживается документационным сайтом. Не каждое действие требует рисунка: короткую последовательность команд удобнее читать текстом.
| Часть | Какие схемы нужны |
|---|---|
| I. Начало | Браузер, приложение, CMS, БД и медиа; путь исходника до работающей страницы |
| II. JS/TS и FP | Композиция функций; ссылки и мутация; порядок асинхронных действий |
| III. Данные и переходы | Произведение и размеченная сумма; граница валидации; автомат допустимых состояний |
| IV. React | Дерево компонентов; поток props и событий; Flux; граф реактивных зависимостей; подписка и очистка |
| V. Интерфейс | Слои CSS; тема и локальная геометрия; композиция слотов; адаптивные состояния |
| VI. Next.js и кеши | Временные шкалы CSR/SSR/SSG/ISR; уровни кеша и ключи; публикация и ревалидация; холодный запрос и отказ |
| VII. API | Один сценарий через разные API; запрос и ответ; потерянный ответ и повтор; конкурентная обработка ключа идемпотентности |
| VIII. Хранилища | ER-диаграмма; колонки и JSONB; строчное и столбцовое чтение; MapReduce shuffle; векторные соседи; реплики и партиции |
| IX. Strapi и S3 | Модель контента; draft/publish; загрузка файла и публичное чтение; запись CMS и объект Garage |
| X. Инструменты и проверки | Исходник, AST, анализ и сборка; границы проверок; цикл изменения; дерево гипотез расследования |
| XI. DevOps | Сеть Compose; pipeline и digest; переключение релиза; резервная копия и восстановление |
Используем flowchart для структуры и зависимостей, sequence diagram для взаимодействий во времени, state diagram для переходов, ER-диаграмму для связей данных. Геометрию интерфейса и численные результаты показываем отдельными макетами или графиками, если схема узлов их не объясняет.
Пример: вычисления и граница эффекта
Это концептуальная схема глав FP/валидации, а не описание конкретной реализации клиента CMS. Стрелки обозначают передачу значений, а не время.
Исходник схемы
flowchart LR IO["HTTP: внешний эффект"] --> Raw["Внешнее значение: unknown"] Raw --> Parse["Разбор и валидация"] Parse --> Data["Допустимые данные"] Parse --> Error["Ошибка разбора"] Data --> Transform["Чистое преобразование"] Transform --> Model["Модель представления"]
Разбор имеет два исхода: данные или ошибка. После успешного разбора преобразование работает с явным входом; сетевой доступ остаётся за его границей. Это позволяет отдельно проверять вычисление и поведение при ошибке источника.
Пример: сумма состояний запроса
Автомат — учебная модель одного запроса без параллельных попыток и отмены. Переходы подписаны событиями; данные каждого состояния уточняются в ADT-главе.
Исходник схемы
stateDiagram-v2 [*] --> Idle Idle --> Loading: Запросить Loading --> Success: Получен результат Loading --> Failure: Получена ошибка Success --> Loading: Обновить Failure --> Loading: Повторить
Здесь выбрано только одно состояние из Idle | Loading | Success | Failure,
поэтому одновременные «загрузка» и «ошибка» не представляются двумя независимыми
флагами. Если при обновлении нужно сохранять прошлые данные, расширяем модель
явно. Одного рисунка недостаточно: тип должен задавать, какие данные доступны
в каждом состоянии, а реализация — соблюдать показанные переходы.
Часть I. Начало и рабочее окружение
Вход: математический бэкграунд, описанный выше, и умение пользоваться компьютером и браузером. Практические инструменты разработки вводятся с нуля. Результат: запускаете проект и можете проследить путь от исходника до страницы.
- Что строим: браузер, сервер, CMS, база и хранилище — архитектура.
- Терминал, Git, ветки и worktree — первый рабочий цикл.
- Node.js, пакеты, pnpm workspace, установка и dev-режим — быстрый старт.
- Основа веб-страницы: HTML, семантика, DOM, CSS и инструменты браузера — веб-платформа.
- Редактор и первые проверки: навигация по коду, диагностика TypeScript, запуск линтера и форматтера, чтение diff — инструменты и первый цикл; действующие команды описаны в проверках.
- Первое изменение и цикл «изменить → проверить → закоммитить» — вводное задание, затем сквозные задания.
Часть II. JavaScript, TypeScript и функциональное мышление
Вход: рабочее окружение из части I. Результат: преобразуете данные и отличаете вычисление от побочного эффекта.
- Значения, переменные, функции, объекты, массивы и модули — JavaScript.
- Замыкания, ссылки, мутация и неизменяемость — JavaScript и граница эффектов.
- Асинхронность: Promise, async/await, ошибки и отмена — асинхронность.
- TypeScript: вывод типов, сужение, generics,
unknown,nullи граница runtime — типы и проверки. - FP: чистые функции, композиция, преобразование коллекций, вычисления и эффекты — преобразования и эффекты.
Сквозной пример этих глав — группировка расписания: входные события преобразуются в дни и площадки без изменения исходного массива. Изучаем наблюдаемое поведение функции, а не требуем запрета всех локальных мутаций.
Часть III. Моделирование данных и переходов
Вход: функции и типы из части II. Результат: описываете допустимые данные, проверяете внешний вход и задаёте переходы состояния.
- Алгебраические типы данных: произведения, суммы, discriminated unions, исчерпывающий разбор и непредставимость недопустимых состояний — ADT и валидация.
- Валидация: внешний JSON как
unknown, Zod, разбор и нормализация — вводная глава ADT и валидация, конкретный обработчик — API и контракты. - Форма данных, бизнес-инварианты и ошибки: границы проверок; лаборатория записи и конкуренции.
- События, reducers, машины состояний, чистое ядро и эффекты — переходы состояния.
Материал для разбора — контракты контента.
Сравните runtime-схему Blocks с TypeScript-типом BlockNode: наличие
discriminatedUnion в Zod само по себе не делает объявленный тип строгой суммой.
Часть IV. React и состояние приложения
Вход: части II–III; понимание событий и переходов состояния. Результат: строите интерфейс из компонентов и выбираете место хранения состояния.
- Декларативный UI, JSX, компоненты, props, композиция и ключи — компоненты и композиция.
- События, локальное состояние, производные значения и подъём состояния — события и владельцы.
- Формы, ошибки ввода и доступность — формы.
- Эффекты, подписки, очистка и жизненный цикл — эффекты и очистка.
- Однонаправленный поток данных, Flux, reducer и Context — Flux и Context.
- Реактивность и FRP: значения во времени, события, зависимости и отмена; связь с React и различия моделей — реактивность и FRP.
- Сравнительная лаборатория управления состоянием: Flux, MobX, атомы и сигналы на одной задаче фильтрации расписания — сравнительная лаборатория.
- Разные владельцы состояния: вводная модель; URL, формы, серверный кеш и долговременное хранение — сравнение владельцев.
Лаборатория нужна для сравнения моделей, а не для подключения всех механизмов к основному сайту. MobX 7.0.6 запускается в отдельном временном каталоге; атомы и сигналы представлены учебными реализациями с явными ограничениями. Workspace-зависимости остаются прежними. Каждое решение сравниваем по потоку данных, обновлениям, эффектам, отладке и сложности. FRP не используем как общее название любой реактивности.
Часть V. Интерфейс, CSS и UIKit
Вход: компоненты, props и композиция из части IV. Результат: собираете адаптивный интерфейс и проверяете компоненты изолированно.
- HTML, семантика, CSS, каскад, раскладка и адаптивность — веб-платформа; материал проекта есть в главе о сайте.
- Mantine, тема, примитивы и составные компоненты — UIKit и API пакета.
- CSS Modules, слои стилей и границы темы — каскад Mantine и UIKit.
- Storybook: stories, Controls, Docs, состояния и примеры — UIKit и Storybook.
- Практика композиции и типографики — семь уроков Storybook.
Уроки доступны в разделе «Обучение» после pnpm --filter @atmanki/ui storybook.
Вводный HTML/CSS читайте до первого упражнения с оформлением;
основы семантики — до упражнений с формами.
Часть VI. Next.js, рендеринг, доставка и кеширование
Вход: React и различие браузера и сервера. Перед серверной загрузкой данных нужен вводный разбор HTTP из части VII; расширенный разбор API идёт после Next.js. Результат: объясняете, где и когда появляется страница, что кешируется и как изменение контента становится видимым пользователю.
Устройство страницы
- App Router, маршруты, layout, Server и Client Components — сайт и Next.js.
- Серверная загрузка контента, адаптеры и границы UIKit — архитектура и устройство сайта.
- CSR, SSR, SSG и ISR: место и время выполнения, HTML, гидратация, свежесть данных и ограничения — способы рендеринга; реализованный SSG/ISR разобран в статической генерации.
- Server Components и способ рендеринга, потоковая передача и Suspense — вводная модель, лаборатория границ ожидания.
Как работает кеш
- Ключ, источник истины, hit/miss, срок жизни, вытеснение и инвалидирование — ключи и уровни кеша, включая исполняемую модель с ручными часами.
- Что сохраняется и где: данные, результат вычисления, HTML, браузер, HTTP-прокси/CDN и сервер приложения — уровни.
- HTTP-кеш: Cache-Control, ETag, условные запросы, публичный и приватный кеш, stale-while-revalidate — вводная глава. Не смешиваем его с состоянием React.
- Кеши Next.js: мемоизация чтений, кеш данных, результата маршрута и клиентский Router Cache — модель и текущие настройки, конкретные сценарии проекта.
- Обновление по времени и событию: теги, пути, новые страницы, закешированный 404, потерянный webhook и ошибка CMS — SSG/ISR и webhook.
- Гонки, массовые одновременные промахи, устаревший ответ и данные пользователя в общем кеше — границы кеширования. Расширенная лаборатория конкурентных запросов — промахи и устаревшая запись. Общую теорию связываем с Redis из части VIII, не предполагая, что текущий сайт хранит там кеш.
Практика и границы проверки
Существующий практикум и серверные проверки дают основу для сценария: публикация в Strapi → webhook → инвалидирование → запрос → новый HTML. Итоговый сценарий дополняет его сравнением холодного и прогретого запроса, изменением записи, новым slug, закешированным 404 и отказом локальной CMS. Отдельно проверяем открытое окно браузера: инвалидирование серверного кеша само по себе не является доставкой нового интерфейса всем активным клиентам.
SSR/CSR и CDN изучаются как модели и варианты доставки, а не как обещание реализованных режимов каждой страницы или настроенного CDN. Поведение кешей сверяется с конфигурацией и кодом; фиксируем отдельно dev и production-сценарии. Руководство Next.js по кешированию без Cache Components служит источником для текущей модели; перед написанием примеров проверяем, какая модель включена в проекте.
Часть VII. HTTP, API и границы доверия
Вход: асинхронность, типы и runtime-валидация. Начальный разбор HTTP читается до серверной загрузки данных в части VI; остальные темы — после неё. Результат: проектируете контракт, выбираете способ взаимодействия, различаете ошибки и объясняете поведение при повторах и потерянном ответе. HTTP-семантика, повторы и идемпотентность и сравнение API дают вводную модель. Глава API разбирает tRPC и webhook проекта. Сравнительная лаборатория, OpenAPI и браузерные границы дополняют концепции практикой.
Семантика HTTP
Вводная глава покрывает сообщения, методы, статусы и If-Match.
- Ресурс и представление, URL, запрос/ответ, заголовки, тело, Content-Type и согласование представления. HTTP-семантика и версии транспорта — разные темы.
- GET, HEAD, POST, PUT, PATCH и DELETE: намерение операции, безопасные и идемпотентные методы. Идемпотентность относится к предполагаемому эффекту, а не к обязательному совпадению ответов; безопасность не означает отсутствие логирования.
- Коды ответа: успешное выполнение, создание, принятие в обработку, отсутствие тела, неверный вход, отсутствие прав, конфликт, лимит и отказ зависимости. Отличаем HTTP-статус от ошибки внутри протокольного ответа.
- ETag, If-Match и условное обновление: защита от потерянных изменений. Кешируемость, безопасность и идемпотентность рассматриваются отдельно; HTTP-кеш подробно разбирается в части VI.
- Аутентификация и авторизация, cookies и Bearer token, CORS и CSRF, серверные секреты и ограничения запроса. Подробную главу о браузерных границах доступа — origin, cookies, CORS и CSRF; текущий webhook разобран в API.
REST и описание контракта
Сравнение API вводит REST и роль OpenAPI; исполняемый контракт с пагинацией и проверкой совместимости — OpenAPI и keyset.
- REST как архитектурный стиль: ресурсы, представления, stateless-взаимодействие, единообразный интерфейс и гипермедиа. Не называем любой JSON endpoint полноценным REST.
- Практический HTTP API: адреса, фильтрация, сортировка, пагинация, ошибки и совместимость. Контракт для чтения и изменения учебной публикации.
- OpenAPI: описание операций и данных, документация, генерация клиента и контрактные проверки. Генерация типов не заменяет runtime-валидацию.
GraphQL, tRPC и gRPC/Protobuf
Вводное сравнение содержит иллюстративные GraphQL/Protobuf-схемы. Лаборатория четырёх API проверяет один сервис через разные adapters.
- GraphQL: схема, query, mutation, subscription, resolvers, выбранные поля, частичные данные и ошибки. Стоимость запроса, N+1 и права доступа; GraphQL не является интерфейсом для произвольного доступа к базе.
- tRPC: общий TypeScript-контракт, Zod, router, context, caller и HTTP-клиент — реализованный пример. Где удобно совместное развитие клиента и сервера, а где важны независимые языки, версии и публичный контракт.
- gRPC: определения сервисов, unary и streaming-вызовы, metadata, статусы, deadlines и отмена. Доступ из браузера и необходимые адаптеры изучаем отдельно.
- Protobuf: схема сообщений, сериализация, генерация кода, номера полей, присутствие значения и эволюция контракта. Protobuf не тождественен gRPC; совместимость формата не гарантирует совместимость бизнес-смысла.
- Сравнение одной задачи по потребителям, контракту, транспортным ограничениям, кешированию, отладке и стоимости сопровождения. REST — стиль, GraphQL — язык запросов и модель выполнения, tRPC — инструмент типизированного RPC, gRPC — RPC-фреймворк, Protobuf — описание и формат сообщений.
Повторы, идемпотентность и побочные эффекты
Вводная глава задаёт закон перехода и границы дедупликации. Транзакционная лаборатория содержит журнал результатов, rollback, повтор после потерянного ответа и протокол опыта с двумя сессиями.
- Ошибка до эффекта, после эффекта и потерянный ответ: timeout не доказывает, что операция не выполнена. Отмена ожидания не является откатом удалённой операции.
- Повтор запроса: условия retry, backoff, jitter, deadline и ограничение попыток. POST/PATCH не считаются идемпотентными только из-за повторяемого payload; прикладной контракт может отдельно обеспечить безопасный повтор операции.
- Ключ идемпотентности: область действия, совпадение ключа и разных данных, конкурентные запросы, хранение результата, срок хранения и повтор после рестарта.
- Атомарность эффекта и фиксации обработки внутри своей БД; внешняя операция за пределами транзакции. Дедупликация и retry сами по себе не гарантируют exactly-once.
- Webhook: проверка входа и доступа, дубли, порядок, повторная доставка, наблюдаемость и восстановление — текущий обработчик. Повтор инвалидирования кеша не используем как доказательство безопасности любой операции записи или внешнего эффекта.
- Эволюция API: добавление и удаление полей, необязательность, версии, старый клиент с новым сервером и обратное сочетание.
Сравнительная практика
Сравнительная лаборатория проверяет получение учебной публикации по ID и изменение. OpenAPI и пагинация дополняют этот контракт чтением списка. Сравниваем варианты API на одинаковом контракте поведения, не смешивая протокол с бизнес-логикой. Моделируем неверный вход, отсутствие записи, запрет доступа, конфликт версии, повтор и потерянный ответ. Практику идемпотентности выполняем после транзакций из части VIII.
В основном проекте уже используются REST Strapi, tRPC и webhook. GraphQL, gRPC, Protobuf и OpenAPI изучаются в отдельных лабораториях и не внедрены в production. Версии временных лабораторий указаны в главах; основной API не переписывается ради сравнения. Итоговый практикум связывает контракт, повтор операции и наблюдаемые результаты.
Источники для подготовки: HTTP Semantics, RFC 9110, REST у Филдинга, GraphQL, tRPC, gRPC, Protobuf.
Часть VIII. Модели данных и системы хранения
Вход: типы, валидация, серверный код и HTTP; для агрегаций — FP из части II. Результат: выбираете модель по запросам и инвариантам, объясняете её цену и отличаете операционные данные от аналитики. Вводные главы: модели хранения, PostgreSQL/JSONB, Redis и доступ к данным/смена СУБД. Это учебный материал, а не новый слой данных сайта. Лаборатории данных, аналитики и ANN, распределённого SQL содержат команды, наблюдения и критерии приёмки дополнительных систем. Основы реляционной модели нужны перед частью IX; распределённые системы, аналитика и векторный поиск — углублённый маршрут, который можно изучить позже.
Реляционная модель, SQL и доступ к данным
Основы ключей, ограничений и конкурентного UPDATE разобраны в PostgreSQL; сравнение доступа вводит ORM и план миграции. Упражнения по JOIN, нормализации, пулу и TypeORM находятся в лабораториях данных.
- Таблицы, ключи, связи, ограничения и нормализация.
- Параметризованные запросы, JOIN, индексы, EXPLAIN, транзакции и конкурентные изменения. Прямой SQL — полноценный инструмент, а не признак устаревшего приложения.
- PostgreSQL и MySQL/MariaDB: переносимые идеи и различия типов, SQL-диалектов,
генерации идентификаторов, дат, сортировок и обработки
NULL. - Драйвер, query builder и ORM на одной задаче. TypeORM в отдельной лаборатории: entities, связи, repositories, Active Record и Data Mapper, миграции схемы.
- Цена абстракций: сгенерированный SQL, N+1, границы транзакций и пул соединений. Типы ORM не заменяют проверку внешнего входа и ограничения базы.
Документы, NoSQL и JSONB
Модели хранения разделяют семейства; JSONB и Redis дают вводные примеры. Практикум SQL/JSONB/Redis задаёт проверки ограничений, TTL и отказа кеша.
- Документная модель, ключ–значение, графы и wide-column: виды запросов, индексы, связи, ограничения и гарантии конкретных систем.
- JSON и JSONB в PostgreSQL: колонки, документ или сочетание обоих; операторы, индексы, проверка структуры и стоимость обновления. Учебный пример — гибкое содержимое публикации в отдельной схеме, без обещания, что Strapi хранит свои Blocks именно таким способом.
- Redis: ключи и структуры данных, кеш, TTL, инвалидирование, поведение при промахе и недоступности. Его вводят для конкретной задачи, а не как обязательный следующий шаг после MySQL или PostgreSQL.
Аналитика и обработка данных
OLTP/OLAP и столбцовое хранение дают вводную модель; MapReduce — исполняемую локальную агрегацию. Лаборатория аналитики сравнивает SQL/JS/MapReduce и вводит event-time окна. Кластер Hadoop/Spark/Flink не нужен для локальной модели; его гарантии нельзя считать проверенными этим опытом.
- OLTP и OLAP: изменить одну запись или агрегировать большой набор событий. Строчное и столбцовое хранение, сжатие и чтение нужных колонок. Различаем столбцовое хранение для аналитики и семейство wide-column.
- Агрегации в JavaScript и SQL GROUP BY на одинаковых учебных событиях. Преобразование, группировка и свёртка; требования к объединению частичных итогов.
- Распределённый MapReduce: map → shuffle и группировка по ключу → reduce.
Партиционирование, передача данных, перекос ключей, повторы задач,
ассоциативность агрегации и воспроизводимость результата.
Метод массива
reduceсам по себе не является распределённым MapReduce. - Локальная модель MapReduce и сравнение результата с SQL GROUP BY. Отдельно показываем ограничения модели: она не проверяет поведение кластера.
- Пакетная и потоковая обработка: конечный набор и непрерывные события, окна, время события и поздние данные. Hadoop — исторический контекст, Spark — тема для дальнейшего знакомства; кластер для вводной практики не нужен.
Векторный поиск и распределённые SQL-системы
NewSQL введён в моделях хранения. Векторный поиск вводит геометрию и точный baseline. Лаборатория ANN сравнивает exact baseline с HNSW; распределённый SQL разбирает quorum, isolation и отказ.
- Embeddings, метрики сходства, точный и приближённый поиск ближайших соседей, фильтрация и оценка качества. Семантическое сходство не равно достоверности ответа.
- Векторное расширение реляционной базы и специализированная векторная БД: сравнение задач, индексов, обновлений и эксплуатации.
- NewSQL и распределённый SQL: шардирование, репликация, транзакции, согласованность, задержки и поведение при отказе узла. Разбираем термин и гарантии конкретной системы вместо общего обещания «масштабируется».
Выбор хранилища и лаборатории
SQL — язык, NoSQL — широкая группа подходов, JSONB — тип данных, столбцовое хранение — организация данных, векторный поиск — способ поиска, а NewSQL — термин для семейства систем. Это разные оси сравнения, а не последовательность замены старой технологии новой.
Для лабораторий используем одинаковые небольшие данные: события и публикации. Сначала формулируем запросы, инварианты, объём и требования к эксплуатации, затем обосновываем выбор. Основная интеграция проекта остаётся через API Strapi: лаборатория использует собственную схему и не пишет во внутренние таблицы CMS. Дополнительные БД, расширения, TypeORM и Redis не подключаются в production-путь. Временные лаборатории используют указанные версии и отдельные учебные schemas/instances. Границы выполненных проверок фиксируются отдельно от готовности инструкции.
Источники для подготовки: JSON/JSONB в PostgreSQL 17, TypeORM, Redis, столбцовая аналитика ClickHouse, исходная работа о MapReduce, pgvector, архитектура распределённой SQL-базы.
Часть IX. Strapi, контент и медиа
Вход: HTTP, схемы и контракты из предыдущих частей. Результат: управляете контентом и проверяете его путь от CMS до страницы.
- Модели, связи, REST, Blocks и draft/publish — CMS и контент.
- Вход в панель, настройки и русский интерфейс — панели.
- Импорт: снимок, dry-run, конфликты, сохранение редакторских изменений — импорт.
- Объектное хранилище и S3 и жизненный цикл медиа: модель, доступ, пути и границы отказов. Интеграция проекта описана в главе о контенте и инструкции Garage.
- Папки, подписи и безопасная реорганизация — медиабиблиотека.
- Публикация → webhook → обновление сайта — редакторский сценарий.
- Когда нужна задача по расписанию — cron Strapi.
Cron сейчас не включён: глава объясняет границы и выбор механизма при появлении конкретной задачи. Детали самостоятельного Strapi-проекта — его README.
Объектное хранилище и S3
Вход: HTTP, устройство CMS и различие между данными записи и содержимым файла. Результат: объясняете выбор хранилища и путь фотографии от загрузки до браузера. Вводная глава объясняет модель и путь чтения, жизненный цикл — связь байтов, записи и публикации. Практикум S3 содержит загрузку, multipart, presigned GET и abort в отдельном приватном bucket. Живое хранилище не проверяется сборкой учебника.
- Задача хранения файлов: файловая система, Docker volume, база данных и объектное хранилище. Когда отдельное хранилище полезно, а когда достаточно локальных файлов; что меняется при пересоздании контейнера.
- Amazon S3 как сервис и S3-совместимый API как интерфейс. Garage как реализация в нашем проекте; совместимость API и её границы.
- Модель объекта: bucket, key, содержимое и metadata. Префикс ключа, «папка» медиабиблиотеки CMS и каталог файловой системы — разные понятия.
- Операции загрузки, чтения, перечисления и удаления; endpoint, region, path-style и multipart upload. Сначала обычная загрузка, затем её усложнения.
- Доступ: серверные credentials, права на bucket, публичные и приватные объекты, подписанные URL. Последние изучаем как механизм, а не как реализованную функцию нашего сайта; совместимость проверяется отдельно.
- Доставка в браузер: S3 API и публичный HTTP-адрес, reverse proxy, Content-Type, кеширование и CORS. Почему ключ объекта и публичный URL могут различаться.
- Интеграция со Strapi: upload provider, файл в Garage, запись и связь в CMS, публикация контента и независимая от неё доступность файла.
- Сохранность: удаление, потерянный ответ и повтор загрузки, резервная копия и восстановление. Отдельно разбираем версионирование и репликацию как возможности хранилищ, не предполагая их наличия в текущем Garage.
Локальный практикум задаёт сценарий: загрузить тестовую фотографию через Strapi, найти запись CMS и ключ объекта, проследить публичный запрос, затем удалить собственный тестовый файл и проверить результат. Исполнение практикума в этом этапе не подтверждено. Используем только учебные данные; отдельно объясняем, почему черновик записи не делает файл приватным и почему хранилище на том же VPS не является резервной копией.
Часть X. Инструменты разработки, качество и диагностика
Вход: опыт выполнения небольших изменений в предыдущих частях. Начальная настройка редактора и запуск проверок вводятся уже в части I. Результат: понимаете роль каждого инструмента, выбираете проверку по риску изменения и воспроизводите её вне редактора и в CI. От исходника до запуска вводит инструменты и модули; лаборатория разделяет типы, lint, format, runtime и поведение. Существующая глава описывает команды и покрытие проекта. Отладчик и профилировщик дополняют вводную главу.
От исходника до работающей программы
- Редактор и language server: поиск символов, переход к определению, подсказки, диагностика и безопасный рефакторинг. Версия TypeScript workspace и версия редактора; результат CLI-проверки как воспроизводимая точка сравнения.
- Парсинг, AST, статический анализ, преобразование кода и выполнение. Различаем проверку типов, удаление типовых аннотаций и сборку приложения.
- ESM, разрешение модулей, aliases, workspace-пакеты, lockfile и границы зависимостей. Сопоставляем dev-режим, тестовый запуск и production-артефакт.
- Dev-сервер, обновление модулей, sourcemaps и отладчик: breakpoints, stack trace, локальные значения. Инструменты браузера: Network, DOM, вычисленные CSS, console, storage и профилирование.
- Storybook для отдельного компонента и dev-сайт для интеграции; возможности и границы изолированной проверки — UIKit.
Что проверяют инструменты
| Инструмент | На какой вопрос отвечает | Что остаётся за границей |
|---|---|---|
| TypeScript typecheck | Согласован ли код с правилами типов и конфигурацией проекта? | Реальные HTTP-данные, бизнес-инварианты и поведение при выполнении |
| Oxlint | Нарушены ли включённые правила статического анализа? | Полная корректность программы и все возможные дефекты |
| Oxfmt | Соответствует ли запись кода принятому форматированию? | Смысл программы и архитектурные решения |
| Сборка | Получается ли артефакт заданного приложения? | Полнота проверок поведения и работа на конкретном VPS |
| Zod | Соответствует ли конкретное значение runtime-схеме? | Правила предметной области, не выраженные этой схемой |
| Jest и Node test runner | Проходят ли заданные сценарии и утверждения? | Непроверенные сценарии и реальная интеграция, заменённая фикстурой |
| Ручная проверка UI и интеграции | Работает ли наблюдаемый сценарий в выбранной среде? | Все устройства, все входы и повторяемость без фиксации условий |
Качество — сочетание независимых свидетельств. Нет правила «тесты прошли, значит типы, доступность и публикация тоже проверены».
Конфигурация и ежедневный цикл
- TypeScript: strict, границы проекта, разрешение импортов, generated types,
noEmit, декларации и отдельная конфигурация Strapi — проверки. - Линтер: включённые правила, область файлов, warnings/errors, исключения и autofix. Учимся объяснять диагностику до исправления или подавления.
- Форматтер: единая конфигурация, проверка и запись, интеграция с редактором. После autofix и форматирования читаем diff; подавления ошибок не становятся способом сделать индикатор зелёным.
- Маленькое изменение → целевые проверки → чтение diff → отдельный коммит. Быстрый feedback в watch-режиме; общий набор и сборка релиза — по задаче и в CI.
- Локальные scripts и GitHub Actions: одинаковый ref, версии, lockfile, переменные и рабочий каталог. Отличаем воспроизводимую проверку от успеха только в одном настроенном редакторе.
Команды и конфигурация имеют один источник: root package.json, Oxlint, Oxfmt, TypeScript и глава проверок. Основные инструменты проекта — Oxlint, Oxfmt, TypeScript, Jest через next/jest и Node test runner для импорта Strapi; учебная программа не меняет этот набор.
Проверка поведения и расследование
- Контрактные тесты, фикстуры, отказ зависимости и интеграционные сценарии — покрытие.
- Ручная проверка интерфейса, доступности и адаптивности — сайт и проверки.
- Симптом → гипотеза → проверка → исправление — лаборатория диагностики и разбор проблем.
- Профилирование: измеряем время, запросы, память и размер ресурсов; отличаем измеренный bottleneck от предположения — отладчик и профилировщик.
Подготовленная лаборатория содержит раздельные примеры ошибки типа, нарушения явно выбранного lint-правила, расхождения форматирования, неверного runtime-входа и дефекта поведения. Сначала предсказываем результат, затем подтверждаем его. Ошибочная сумма проходит typecheck, но нарушает контракт; исправление проверяется тестом. Это временные файлы, не изменение стека проекта.
Часть XI. DevOps и эксплуатация
Вход: устройство приложения, API и CMS; подход к проверкам из части X. Результат: понимаете состав релиза, умеете диагностировать запуск и проверять восстановление.
- Linux, процессы, права и SSH — основы и локальные упражнения.
- Docker: образы, контейнеры, Compose, сеть, тома и readiness — жизненный цикл сервиса и инфраструктура.
- PostgreSQL, хранение данных и жизненный цикл базы — жизненный цикл, миграции схемы и инфраструктура.
- Caddy, DNS, HTTPS и reverse proxy — DNS/TLS, прокси и HTTP/2–HTTP/3, инфраструктура.
- Конфигурация и секреты — настройки. Конфигурация своего экземпляра вводит единую identity и вычисление адресов; подключение к delivery — следующий этап.
- CI/CD: GitHub Actions, GHCR, digest и релизы — основы, лаборатория чтения релиза и деплой.
- Логи, метрики и трассировки — наблюдаемость; резервные копии, восстановление и откат — эксплуатация.
- Ограничения одного VPS и границы гарантий — ограничения.
Production-образы собираются в GitHub CI; VPS получает готовый релиз. Учебные сбои и восстановление выполняются в изолированной локальной среде.
Дополнительный маршрут: от PHP и MySQL/MariaDB
Для читателя с опытом PHP этот маршрут связывает знакомые задачи с материалом учебника. Он не предполагает, что PHP, прямой SQL или MySQL/MariaDB обязательно нужно заменить. Глава перехода содержит сравнение функций, карту типов, сверку и cutover; существующий импорт сайта в Strapi не является примером переноса PHP-кода или MySQL-базы.
- Сравнить обработку запроса в исходном PHP-приложении с серверным JavaScript: жизненный цикл процесса, async/await, ошибки, соединения и состояние между запросами.
- Разделить изменения: язык приложения, база данных и способ доступа к ней. Смена PHP на TypeScript не требует одновременной смены СУБД или внедрения ORM.
- Перенести одну функцию: PHP и параметризованный SQL → TypeScript и SQL → query builder/ORM. Сравнить поведение и реальные запросы; TypeORM — инструмент отдельной лаборатории, а не зависимость production-проекта.
- Подготовить миграцию в PostgreSQL: карта типов и связей, преобразование данных, пробный перенос, сверка количества записей и содержимого, новая запись во время переноса, переключение и границы отката. Отдельно отличить миграции схемы от переноса данных между СУБД.
- Добавить кеш Redis только к измеренной задаче: источник истины, ключи, срок жизни, инвалидирование и работа приложения без кеша.
- Выполнить постепенный переход на изолированных учебных данных, проверить контракт старого и нового пути и записать результаты. Автоматической миграции реального приложения эта глава не обещает.
Сквозной практикум
Сквозные задания связывают упражнения отдельных глав в итоговые сценарии с наблюдаемым результатом:
- Преобразовать события CMS в проверенные данные и адаптивное расписание.
- Сравнить модели состояния на одном фильтре, объяснить выбранное решение.
- Проследить draft → publish → webhook → обновлённую страницу без rebuild.
- Сравнить способы API на одном контракте и проверить повтор операции после потерянного ответа.
- Сравнить агрегирование учебных событий в JavaScript, SQL и локальной модели MapReduce.
- Обосновать выбор колонок или JSONB и сравнить точный и приближённый векторный поиск.
- Проверить свежесть страницы после публикации и объяснить поведение каждого кеша.
- Проверить отказ зависимости, выпустить релиз и восстановить учебную копию.
Для каждого сценария практикум указывает материалы, порядок действий и приёмку. Выполнение читателем не добавляет функцию в production автоматически.
Справочник и устройство учебника
- Команды, термины, версии и официальные источники.
- Ограничения и безопасность.
- Публикация документационного сайта.
- Интерактивные главы MDX.
История проекта
Эти документы фиксируют решения и проверки на конкретную дату. Они не заменяют текущие инструкции и не являются подтверждением нынешнего состояния VPS.