Перейти к содержанию

Как устроен сайт на MkDocs Material и GitHub Pages

Разбор того, что происходит от Markdown-файла до публикации сайта и что реально загружается в браузере при открытии страницы.


Введение

Когда я начинал делать SkillMatrix, задача выглядела довольно простой.

Есть папка с Markdown-файлами. Нужно превратить её в удобный сайт для чтения.

Сначала я даже написал собственный генератор на Python. Markdown превращался в HTML, работали шаблоны, постепенно появилась навигация, индекс страниц и оформление.

Но довольно быстро стало понятно, что я начинаю писать собственный статический генератор сайтов.

В итоге после перебора нескольких вариантов я остановился на MkDocs.

Не потому что это модный инструмент. А потому что он оказался самым простым и понятным способом получить полноценный сайт из обычной папки с Markdown-документами.

Сейчас сайт SkillMatrix работает на связке:

Markdown
    ↓
MkDocs
    ↓
Material Theme
    ↓
GitHub Pages

Разберёмся, что происходит внутри.


Что такое MkDocs

MkDocs — это статический генератор сайтов на Python.

Его задача очень простая:

Markdown → HTML

Во время сборки MkDocs читает все Markdown-файлы, генерирует HTML-страницы и складывает результат в отдельную папку.

После этого никакой Python больше не нужен.

Получается полностью статический сайт.

Что значит "статический"

Статический сайт — это набор готовых файлов:

index.html
page1.html
page2.html

main.css
bundle.js

search_index.json

Когда пользователь открывает страницу, сервер просто отдаёт эти файлы.

Никаких запросов к базе данных.

Никакой серверной логики.

Никакого PHP.

Никакого Django.

Никакого Flask.

Фактически GitHub Pages работает как обычное файловое хранилище.


Что такое Material for MkDocs

Многие думают, что MkDocs и Material — это одно и то же.

На самом деле нет.

  • MkDocs отвечает за генерацию страниц.
  • Material отвечает за внешний вид и пользовательский интерфейс.

Если убрать Material, останется просто набор HTML-страниц.

Material добавляет всё то, что делает документацию похожей на современный сайт.

Что Material делает автоматически

Из коробки появляются:

Навигация

Левое меню строится автоматически на основе структуры документации.

Манифест

Про CRM
 ├─ Что такое CRM
 ├─ Путь клиента
 └─ Почему я занимаюсь CRM

Про ремонт
 └─ Как я вешал зеркало

Оглавление страницы

Правая колонка строится из заголовков статьи.

Во что я верю
Честность важнее правоты
Роль ИИ
Что я собираю

Поиск

Поиск работает прямо в браузере.

  • Без сервера.
  • Без базы данных.
  • Все статьи индексируются во время сборки.

Адаптивный интерфейс

  • На телефоне меню превращается в выезжающую панель.
  • На компьютере показываются две боковые колонки.

Темизация

Material умеет:

  • светлую тему;
  • тёмную тему;
  • пользовательские цветовые схемы;
  • переключение через localStorage.

Подсветка кода

Автоматически оформляет:

print("Hello")

Дополнительные возможности

Также Material добавляет:

  • хлебные крошки;
  • иконки;
  • вкладки;
  • предупреждения;
  • карточки;
  • диаграммы Mermaid;
  • поддержку LaTeX;
  • поиск по заголовкам.

По сути Material — это уже готовый фронтенд-фреймворк для документации.


Как устроен процесс публикации

Сборка выполняется командой:

mkdocs build

После этого создаётся папка:

site/

В ней лежит полностью готовый сайт.

Публикация через GitHub Pages

Для публикации используется команда:

mkdocs gh-deploy

Что происходит внутри:

  1. MkDocs выполняет сборку сайта.
  2. Создаёт временную ветку gh-pages.
  3. Копирует туда содержимое папки site.
  4. Делает commit.
  5. Отправляет изменения в GitHub.
  6. GitHub Pages начинает раздавать эти файлы.

Схема выглядит так:

Markdown
    ↓
mkdocs build
    ↓
site/
    ↓
mkdocs gh-deploy
    ↓
gh-pages
    ↓
GitHub Pages
    ↓
https://skillmatrix.ru

Никаких серверов я не арендую.

Никаких VPS не настраиваю.

Весь сайт живёт внутри GitHub Pages.


Что реально загружается при открытии страницы

Я снял HAR-лог главной страницы SkillMatrix и посмотрел реальные тайминги.

Полная загрузка страницы:

onLoad ≈ 440 мс

Для статического сайта это отличный результат.

Все загружаемые файлы

Файл Тип Время Размер
HTML-документ document 64 мс 6.6 KB
main.css stylesheet 94 мс 23.7 KB
Google Fonts CSS stylesheet 36 мс 2.3 KB
bundle.js script 135 мс 35.5 KB
Roboto Latin font 194 мс 37.5 KB
Roboto Cyrillic font 101 мс 19.6 KB
Roboto Symbols font 174 мс 16.7 KB
Roboto Math font 91 мс 36.3 KB
search_index.json JSON 65 мс 28.5 KB
search worker script 70 мс 0.15 KB
lunr stemmer script 80 мс 1.5 KB
lunr.ru script 49 мс 3.5 KB
favicon image 46 мс 2.1 KB

Общая статистика

Параметр Значение
Всего файлов 13
Общий вес ~216 KB
Полная загрузка ~440 мс
Самый тяжёлый файл bundle.js
Самый медленный файл Roboto Latin

Как выглядит процесс загрузки

Когда пользователь открывает страницу:

1. Загружается HTML
2. Браузер находит CSS
3. Загружается CSS
4. Загружается JavaScript
5. Загружаются шрифты
6. Загружается индекс поиска
7. Инициализируется поиск
8. Страница готова

Упрощённая временная диаграмма:

0ms

├── HTML (64ms)

├── CSS (94ms)

├── Google Fonts CSS (36ms)

├── bundle.js (135ms)

├── Шрифты (91-194ms)

├── search_index.json (65ms)

├── search worker (70ms)

├── lunr stemmer (80ms)

└── lunr.ru (49ms)

440ms
Страница полностью загружена

Большинство ресурсов загружается параллельно благодаря HTTP/2 и HTTP/3.


Как работает поиск

Поиск полностью клиентский.

Никакого сервера для поиска нет.

Что участвует в поиске

Во время сборки создаётся файл:

search/search_index.json

В него попадают:

  • заголовки;
  • ссылки;
  • текст статей.

Что происходит при поиске

Пользователь вводит запрос:

CRM

Дальше:

  1. Поисковый воркер получает запрос.
  2. Lunr.js разбивает текст на токены.
  3. Выполняется стемминг.
  4. Производится поиск по индексу.
  5. Результаты сортируются.
  6. Показываются пользователю.

Русский язык

Material использует расширение Lunr для русского языка.

Например:

маркетинг
маркетинга
маркетингу

Приводятся к общей основе.

Поэтому поиск работает корректно даже по склонениям.


Что занимает больше всего места

Если посмотреть на распределение ресурсов:

Тип Вес
Шрифты ~110 KB
JavaScript ~40 KB
Индекс поиска ~28 KB
CSS ~26 KB
Остальное ~12 KB

Самые тяжёлые ресурсы — вовсе не HTML.

Большую часть занимают шрифты Roboto.

Именно они являются главным ограничением по скорости загрузки.


Почему сайт работает быстро

Есть несколько причин.

Статика

Все страницы уже готовы заранее.

Ничего не генерируется на сервере.

GitHub Pages

Файлы раздаются через CDN GitHub.

Повторные посещения часто получают ресурсы из кеша.

Сжатие

HTML, CSS, JavaScript и JSON передаются в сжатом виде.

Минификация

CSS и JavaScript уже оптимизированы во время сборки.

Параллельная загрузка

Браузер не ждёт завершения одного запроса для начала следующего.


Итоги

После нескольких экспериментов с собственным генератором, шаблонами и альтернативными решениями я в итоге остановился на связке:

MkDocs
+
Material
+
GitHub Pages

На практике это дало:

  • простую структуру проекта;
  • обычные Markdown-файлы;
  • встроенный поиск;
  • автоматическую навигацию;
  • адаптивный интерфейс;
  • автоматическую публикацию через gh-deploy;
  • полную загрузку сайта примерно за 440 мс.

Для проекта, который по сути является библиотекой текстов и заметок, этого оказалось более чем достаточно.

А главное — всё внимание можно тратить на контент, а не на поддержку собственного генератора сайтов.