Архитектура
Сайт "Вселенная IT" — связка сервисов с единой навигацией и перекрёстными ссылками. Текст и структура знаний живут в репозитории it-knowledge-base; тяжёлый интерактив и длинный код вынесены на отдельные домены, чтобы энциклопедию можно было собирать и отдавать быстро.
Общая идея близка к многоуровневой архитектуре и паттернам микросервисов, но в упрощённом виде — без оркестратора контейнеров на каждый абзац статьи. Подробнее о выборе архитектуры — в Основах архитектуры и Архитектурных паттернах.
Общая схема
Сборка и выкат связаны с DevOps и CI/CD. Исходники хранятся в Git — см. Основы работы с Git.
Роли сервисов
| Сервис | Назначение | Технология (типично) |
|---|---|---|
| spirzen.ru | Энциклопедия, лаборатория, глоссарий, поиск, навигация | Docusaurus 3 + React 19, статический экспорт |
| code.spirzen.ru | Запускаемые листинги, встраивание через /e/embed/<slug>/ | Отдельный Astro/Vite-проект |
| play.spirzen.ru | Тренажёры, эмуляторы, визуализаторы через /p/embed/<slug>/ | Отдельный Astro/Vite-проект |
| assets.spirzen.ru | Скриншоты, диаграммы, тяжёлые PNG/WebP | CDN / object storage |
Разделение сделано осознанно.
- Размер бандла. Интерактив из сотен демо держится отдельно от основного JS-чанка энциклопедии.
- Независимые релизы. Тренажёр SQL можно обновить без полной пересборки энциклопедии — тот же принцип слабой связанности, что в REST-интеграциях.
- Изоляция. iframe + postMessage с проверкой origin задаёт контролируемую границу между контентом и исполняемым кодом. См. также HTTP как основу веб-интеграций и HTTPS.
Паттерны в архитектуре
Ниже — паттерны, которые можно узнать по энциклопедии, и то, как они проявляются именно в "Вселенной IT".
| Паттерн | Суть | Где в проекте | Теория в энциклопедии |
|---|---|---|---|
| Static Site Generation (SSG) | HTML/JS собираются заранее, сервер отдаёт файлы | docusaurus build → spirzen.ru | Как работают сайты, CDN |
| SPA с гидратацией | После загрузки HTML React "оживляет" страницу | Docusaurus + React | SPA и frontend-стек |
| Разделение по bounded context | У каждого домена своя зона ответственности | spirzen / code / play / assets | Паттерны микросервисов |
| Embed / Facade | Статья видит простой компонент, внутри — сложный iframe | ExternalPlayEmbed, ExternalCodeEmbed | Модульность |
| Lazy loading | Код грузится, когда нужен | lazyMdxDemoImports, lazyDemoInView | Proxy и lazy loading |
| Code splitting | Один бандл режется на чанки | Webpack/Rspack splitChunks | SPA и bundler |
| Compile-time transform | Markdown меняется до рендера | remark-плагины | Markdown в вебе |
| Client-side index | Поиск по заранее собранному JSON | doc-search-index.json + DocSearch | Основы БД и индексы (аналогия) |
| Redirect / compatibility layer | Старые URL ведут на новые | plugin-client-redirects | HTTP-справочник |
| Gate / deferred init | Тяжёлое стартует по действию пользователя | Click-to-load, EmbedClickGate | Polling и push (отложенная загрузка данных) |
| Cross-cutting enhancement | Общая логика без дублирования в статьях | DocItem/Layout, articleMetaEnhancement | Составные паттерны |
| Theme extension (swizzle) | Подмена частей фреймворка | src/theme/* | Основы архитектуры |
Паттерны сознательно прагматичные — приоритет скорости сборки тысяч статей и предсказуемости для читателя важнее формальной "чистоты" монолита.
Интеграции и способы взаимодействия
1. spirzen.ru ↔ читатель (HTTP)
Браузер запрашивает статику по HTTP. После первой загрузки навигация между статьями идёт как SPA — без полной перезагрузки страницы, с подгрузкой JS-чанков маршрута.
2. spirzen.ru ↔ code.spirzen.ru / play.spirzen.ru (iframe + postMessage)
| Этап | Кто | Что происходит |
|---|---|---|
| Разметка | MDX-статья | <ExternalPlayEmbed example="slug" /> |
| Обёртка | React на spirzen.ru | Click-to-load заглушка, затем <iframe src="…/p/embed/slug/"> |
| Выполнение | play / code | Демо или листинг в изолированном документе |
| Обратная связь | iframe → родитель | postMessage с высотой; проверка origin |
| Тема | query ?theme=light или dark | Согласование яркости с переключателем на spirzen.ru |
Это синхронная встраиваемая интеграция — один общий контракт (slug в URL embed, доверенные origins в src/constants/) вместо отдельного REST-API на каждую статью.
3. spirzen.ru ↔ assets.spirzen.ru (прямые URL)
Картинки в Markdown — . Браузер качает файл напрямую; CDN кэширует у края сети. Энциклопедия не проксирует байты иллюстраций.
4. Репозиторий ↔ сборка (npm-скрипты)
Перед docusaurus build скрипты в scripts/ генерируют артефакты.
| Скрипт | Артефакт | Зачем |
|---|---|---|
docs:wiki-links | wikiLinkIndex.json | Разрешение [[wiki-ссылок]] в remark |
docs:search-index | doc-search-index.json | Клиентский поиск |
docs:redirects | docLegacyRedirects.json | Редиректы со старых путей |
docs:collection-titles | collectionDocTitles.json | Заголовки в хабах подборок |
Подробнее — в главе Данные и скрипты.
5. remark ↔ MDX (этап компиляции)
remark-плагины — мост между авторским Markdown и бандлом React. wikiLink.js подставляет ссылки; lazyMdxDemoImports.js переписывает import компонентов на lazy-обёртки. Это интеграция на этапе сборки, в рантайме браузера remark уже не работает.
6. localStorage ↔ тема оформления
Палитра дизайна (data-design) и light/dark (data-theme) сохраняются в браузере. Client modules синхронизируют атрибуты при SPA-переходах — см. Темы и стили.
Что происходит при npm start / npm run build
Цепочка из package.json.
"start": "npm run docs:wiki-links && npm run docs:search-index && npm run docs:redirects && cross-env NODE_OPTIONS=--max-old-space-size=16384 docusaurus start"
| Шаг | Скрипт | Результат |
|---|---|---|
| 1 | docs:wiki-links | src/data/wikiLinkIndex.json, индекс для [[wiki-ссылок]] |
| 2 | docs:search-index | static/doc-search-index.json, клиентский поиск (Ctrl+K) |
| 3 | docs:redirects | src/data/docLegacyRedirects.json, редиректы со старых URL |
| 4 | docusaurus start/build | Webpack/Rspack-сборка сайта |
Для продакшена дополнительно запускается docs:collection-titles — заголовки статей в подборках.
Слои приложения spirzen.ru
Каждый пункт — отдельный слой приложения в смысле многоуровневой схемы.
1. Контент (docs/)
- Файлы
.mdи.mdx— статьи, разделы, подборки. - Frontmatter с полями
title,description,slug,tags,relatedи др. - MDX позволяет
importReact-компонентов прямо в статью. routeBasePath: '/'ставит документацию в корень сайта (/encyclopedia/...).
Текстовая основа — Markdown и языки разметки.
2. Презентация (src/theme/)
Swizzle-компоненты Docusaurus — обёртка статьи, navbar, sidebar, карточки. Здесь вшиты PDF-экспорт, прогресс главы и блок "Смотрите также" без импорта в каждой статье.
3. Интерактив (src/components/)
- Embed —
ExternalPlayEmbed,ExternalCodeEmbed(iframe). - Хабы —
CollectionHub,LabTrainersHub,GettingStartedPaths. - Поиск — собственный DocSearch вместо Algolia.
4. Данные (src/data/)
JSON и JS-модули с подборками, иконками технологий, палитрами дизайна и словарями терминов. Часть генерируется скриптами, часть редактируется вручную.
5. Стили (src/css/)
Infima (тема Docusaurus) плюс кастомная система --d-* токенов и 25+ палитр data-design. См. HTML и CSS.
Поток запроса читателя
- Браузер запрашивает HTML/JS/CSS с spirzen.ru (или localhost:3000).
- Client modules (
itDesignThemeInit,limitRoutePrefetch) выполняются на клиенте до гидратации React. - При открытии статьи MDX рендерит markdown; remark-плагины уже преобразовали
[[ссылки]]и lazy-import компонентов. ExternalPlayEmbedпоказывает click-to-load заглушку; после клика iframe грузит play.spirzen.ru и шлёт postMessage с высотой.- Поиск (Ctrl+K) читает
doc-search-index.jsonи ищет локально в браузере — клиентский поиск.
Производительность как часть архитектуры
Решения заложены в нескольких местах сразу.
- remark
lazyMdxDemoImportsпереписывает статическийimport Foo from '@site/...'в MDX вlazyDemoInView/lazyExternalEmbed. - Webpack
splitChunksвdocusaurus.config.jsвыделяет отдельные чанки для React, Docusaurus, Prism, Mermaid и embed-компонентов. limitRoutePrefetchпропускает prefetch тяжёлых маршрутов (/encyclopedia/,/lab/,/about/interactive).- Click-to-load iframe откладывает ws:// и тяжёлые демо до клика читателя.
На Windows в dev по умолчанию отключён Rspack faster (IT_DOCUSAURUS_FASTER=1 для включения) — иначе возможен EMFILE при тысячах файлов.
Где что искать в репозитории
it-knowledge-base/
├── docs/ # Контент (статьи)
├── src/
│ ├── components/ # React для MDX и темы
│ ├── theme/ # Swizzle Docusaurus
│ ├── data/ # Статические данные
│ ├── css/ # Глобальные стили
│ ├── remark/ # Плагины markdown
│ ├── clientModules/ # Клиентский bootstrap
│ ├── constants/ # URL embed-сервисов
│ └── pages/ # Главная (отдельно от docs)
├── scripts/ # Генераторы перед сборкой
├── static/ # Файлы как есть (favicon, поисковый JSON)
├── docusaurus.config.js # Главный конфиг
├── sidebars.js # Боковое меню
└── package.json # Зависимости и npm-скрипты
Глоссарий терминов
Краткие определения в контексте "Вселенной IT". Якоря (#сервис) — для ссылок из других глав этого раздела.
Сервис
Отдельно развёрнутое приложение или статический сайт с своим доменом и зоной ответственности. spirzen.ru, code.spirzen.ru, play.spirzen.ru и assets.spirzen.ru — четыре сервиса витрины знаний. Теория — паттерны микросервисов.
Навигация
Способ перемещения читателя по материалам — navbar, sidebar, подборки, wiki-ссылки, поиск, пагинация статей, карта на главной. Единая навигация связывает все домены через ссылки в тексте.
Репозиторий
Git-хранилище исходников (it-knowledge-base на GitHub). В репозитории лежат docs/, src/, скрипты и конфиги; из него собирается spirzen.ru. См. Основы Git.
Интерактив
Запускаемый в браузере опыт — тренажёры, эмуляторы, игры, пошаговые схемы. В проекте основная масса интерактива на play.spirzen.ru и встраивается через Embed. Витрина — /about/interactive.
Домен
Имя хоста в URL (spirzen.ru, code.spirzen.ru). Отдельный домен даёт изоляцию cookies, origin для postMessage и независимый деплой. См. CDN и DNS.
Листинг
Фрагмент исходного кода в статье или на code.spirzen.ru — часто с подсветкой и возможностью запуска. Листинги на code отделены от текста энциклопедии, чтобы не раздувать бандл.
Визуализатор
Интерактивная схема или анимация (алгоритм, сеть, архитектура ПК). На play.spirzen.ru визуализаторы грузятся в iframe только после click-to-load.
Бандл
Один собранный JS-файл (или группа), который браузер скачивает для работы сайта. Цель архитектуры — держать бандл spirzen.ru лёгким, вынося демо на play/code. См. SPA и bundler.
Чанк
Часть бандла, подгружаемая отдельно (lazy route, embed-компонент). Webpack/Rspack splitChunks режет vendor-react, vendor-docusaurus, async-демо. Подробнее — docusaurus.config.js.
Origin
Пара схема + хост + порт (https://play.spirzen.ru). postMessage принимается только с доверенных origin из constants/codeExamples.js и playExamples.js. См. безопасность веба.
Продакшен
Боевая среда, куда попадает результат npm run build после деплоя. Продакшен-URL embed заданы в docusaurus.config.js (customFields). См. DevOps, CI/CD.
Индекс
Заранее собранная структура для быстрого поиска — wikiLinkIndex.json, doc-search-index.json. Аналогия с индексом в БД, но файл лежит в static/ и читается в браузере.
Клиентский поиск
Поиск по статьям без сервера и без Algolia — Ctrl+K, JSON-индекс, fuzzy-match в docSearchEngine.js. Подробнее — Данные и скрипты.
Редирект
HTTP-перенаправление со старого URL на новый после переименования папок энциклопедии. Источники — docLegacyRedirects.json и ручная карта в config. См. HTTP.
Слой приложения
Логический уровень системы — контент, презентация, интерактив, данные, стили. Соответствует слоям в архитектуре ПО.
Frontmatter
YAML-блок между --- в начале .md/.mdx — title, description, slug, теги. Frontmatter читают Docusaurus и скрипты docs:search-index. Правила — в манифесте и .cursor/rules.
Markdown
Язык разметки текста; в проекте расширен до MDX (Markdown + JSX). См. Текст в веб-технологиях.
Swizzle-компонент
Копия компонента темы Docusaurus в src/theme/, подменяющая стандартную реализацию. Позволяет менять обёртку статьи, navbar, sidebar без форка фреймворка.
Обёртка
React-компонент, который окружает контент — DocItem/Layout, Embed-оболочка вокруг iframe. Паттерн Facade из структурных паттернов.
Navbar
Верхняя панель сайта — логотип, "Энциклопедия", "Указатель", поиск. Настраивается в themeConfig.navbar и swizzle src/theme/Navbar/.
Sidebar
Боковое меню документации из sidebars.js — дерево разделов, autogenerated для энциклопедии. См. sidebars.js.
Карточка
Компактный блок со ссылкой на статью (DocCard, карточки подборок на главной). Рендерится темой и хабами.
Экспорт
Выгрузка статьи в PDF через ArticlePdfExport (html2canvas + jsPDF) — кнопка в layout статьи.
Embed
Встраивание внешнего контента в страницу. В проекте — React-компонент + iframe на code/play. Отличие от простой ссылки — демо живёт внутри статьи.
Хаб
Страница-каталог — CollectionHub, LabTrainersHub, GettingStartedPaths. Собирает маршруты из src/data/ в один обзор.
Algolia
SaaS-поиск, который Docusaurus поддерживает из коробки. В "Вселенной IT" заменён клиентским поиском из соображений доступности и автономности.
Палитра дизайна
Визуальная тема оформления (data-design) — Matrix, Sakura, "Оригинал" и др. Независима от light/dark. См. Темы и стили.
Infima
CSS-фреймворк по умолчанию в Docusaurus (переменные --ifm-*, сетка, типографика). Кастомные палитры маппятся на Infima через it-design-bridge.css.
Гидратация
Процесс, когда React подключается к уже отрендеренному HTML и делает страницу интерактивной. До гидратации работают client modules и inline-скрипт data-design. См. React.
Заглушка
Плейсхолдер до загрузки тяжёлого блока — EmbedClickGate с кнопкой "Запустить демо". Снижает нагрузку при открытии длинной статьи.
iframe
HTML-элемент вложенного документа. Демо с play/code выполняется в изолированном контексте внутри iframe. См. веб-API браузера.
postMessage
API window.postMessage для обмена данными между окном и iframe. Play шлёт высоту контента; spirzen.ru слушает только доверенные origin.
remark
Экосистема плагинов для обработки Markdown в AST. Плагины в src/remark/ подключены в docusaurus.config.js. См. Markdown.
Click-to-load
Паттерн — iframe и WebSocket демо стартуют только после клика по заглушке. Реализован в ExternalPlayEmbed / ExternalCodeEmbed.
Rspack
Быстрый бандлер (альтернатива Webpack), включается через @docusaurus/faster и future.faster в config.
EMFILE
Ошибка ОС "слишком много открытых файлов". На Windows dev с тысячами MDX Rspack faster по умолчанию выключен.
Связь с остальными главами раздела
- docusaurus.config.js — конфигурация сборки, плагины, webpack.
- package.json и стек — зависимости и npm-скрипты.
- Компоненты — Embed, хабы, MDX.
- Темы и стили — Infima, палитра дизайна.
- Данные и скрипты — remark, индекс, генераторы.