Как я переносил блог с WordPress на статику
Постоянные подписчики могли заметить, что сегодня сайт выглядит немного иначе. Причина заключается в отказе от движка WordPress. Смена дизайна является побочным эффектом. Сейчас удобное время, чтобы заодно сменить/улучшить и его.
WordPress был выбран в 2009-м году, когда я только начал вести «Записки программиста». Движок верой и правдой служил мне все эти годы. Вы спросите, на какой же движок я его променял? А ни на какой. Теперь сайт работает без движка. Используются только HTML и CSS. Нет даже генератора статических страниц. Концепция блога на HTML была предложена Алексом Nevkontakte.
Непосредственно к WordPress у меня претензий нет, разве что мелкие придирки. Претензия к факту наличия какого-либо движка. Если есть движок, то в масштабах 10+ лет обновляется сам движок, его плагины, а также их зависимости. Нужно ставить апдейты. При этом что-то где-то неизбежно ломается. Проверено неоднократно. Постоянно выяснять, в каком из более 1000 постов что-то поползло, почему перестала работать отложенная публикация, какие RSS-читалки не переваривают новую ленту, и так далее – удовольствие ниже среднего.
Есть вариант не обновляться. Но тогда имеем другую проблему. В масштабах все тех же ±10 лет возникает необходимость менять хостинг. Если 10 лет не обновляться, то воспроизвести похожее окружение для работы движка становится проблематично. Впервые я это обнаружил, когда переносил блог в 2018-м году. Уже тогда найти пакет с PHP 5.6 было непросто. Выяснять, насколько это просто сегодня или в условном 2035-м году, желания у меня нет.
Кто-то возразит, что статика – это же неудобно. А как же WYSIWYG редактор? А если я хочу подправить заголовок или подвал на всех страницах? А как быть с метками и пагинацией? И далее по списку.
WYSIWYG я лично никогда и не пользовался, предпочитая писать посты в HTML. WordPress разве что проставлял за меня <p> и </p>. Мне не трудно писать их и самому. Заголовки и подвалы правятся редко. При необходимости задача решается тривиальным скриптом на Python.
От меток я решил отказаться. Категоризировать посты с их помощью бывает непросто. А ведь в сущности метки – это всего лишь эквивалент предметного указателя из книг. Принимая во внимание, что на сайте всегда была форма поиска через Google, практический смысл меток не ясен.
С пагинацией интереснее. Действительно, если разбить историю блога на страницы, где каждая страница содержит по 10 постов, то обновлять эти страницы будет неудобно. Но давайте посчитаем. Как часто публикуются новые посты? Даже в самые продуктивные годы я не писал более двух постов в неделю. Выходит, порядка 100 постов в год – это максимум. Так давайте просто сделаем архив по годам. Страница каждого года содержит перечень постов с датой публикации, заголовком и ссылкой на пост.
Алгоритм добавления новой статьи получается следующим:
- Если пишем первую статью в этом году, то создать страницу архива за год и сослаться на нее с главной страницы;
- Добавить статью в архив за соответствующий год;
- Добавить статью в список последних N постов на главной странице;
- Добавить статью в RSS-ленту, если она есть;
- Написать статью;
- Сделать
rsync;
Даты и заголовки статей не меняются, или меняются исключительно редко. Таким образом, поддерживать описанную структуру очень просто. При желании публикацию можно автоматизировать все тем же скриптом на Python, хотя он и не обязателен. Кстати, RSS-ленту я решил оставить. Судя по логам, многие ею пользуются.
На данном этапе задумка начинает походить на рабочую. Осталось только проверить ее на практике.
Хоть новая версия сайта и без движка, а код писать придется. Во-первых, раз мы меняем структуру сайта, то нужны новые HTML и CSS. Под это дело неплохо бы улучшить совместимость с мобильными устройствами. Во-вторых, старые посты не хочется терять, ровно как и держать их статическую копию со старым дизайном. Неплохо бы предусмотреть миграцию. Вот только кода будет много, код будет скучным, и писать мне его лень. Поэтому задача была делегирована Claude Sonnet 4.
Клод мастерски верстает сайты и пишет на Python. Наброски нового блога были получены за два вечера. В общей сложности ИИ сгенерировал ~300 строк на HTML/CSS и еще ~1500 строк кода на Python. Большая часть этого кода вряд ли будет кому-то интересна. Он занимается загрузкой существующих постов, добавлением к ним заголовков и подвалов страниц, исправлением внутренних URL и генерацией архивов по годам. Также создается конфиг для Nginx, чтобы сервер перенаправлял пользователей со старых URL на новые.
В качестве более-менее интересного скрипта можно отметить prettify.py. Он занимается тем, что улучшает типографическое оформление постов. Например, если в тексте есть короткий предлог, за которым идет пробел, то пробел заменяется на . Таким образом, предлог не останется одиноко висеть в правой части экрана в случае переноса строки. В общем, скрипт автоматизирует то, что раньше я делал вручную, когда видел на сайте некрасивый по моему субъективному мнению текст.
Fun fact! Теоретически, описанная проблема решается на уровне CSS, указанием text-wrap: pretty;. Но как минимум в современном Firefox это не работает, а в прочих браузерах может работать по-разному. Вот и приходится редактировать HTML.
На генерацию sitemap.xml было решено забить. Есть версия, что новые посты должны хорошо индексироваться поисковыми системами и без него. Если гипотеза не подтвердится, то добавить sitemap.xml не трудно. Просто в алгоритме написания новой статьи появится еще один шаг. Что же до переиндексации старых постов, то она меня не особо волнует. Если я и правлю старые посты, то правки минимальные. Торопиться здесь некуда.
От подсветки синтаксиса я тоже отказался. В теории, ее можно реализовать на JavaScript. Но на практике подсветка часто ломается. Например, в коде на Bash, в отрывках из какого-нибудь REPL, когда длинные строки разбиваются при помощи ⏎, и так далее. Как результат, какой-то код имеет подсветку, а в каком-то она отключена. Лучше уж без подсветки, чтобы весь код выглядел одинаково.
Что еще пошло под нож – это статистика LiveInternet. Она уже много лет показывает ерунду. Примерно с тех пор, как браузеры озаботились приватностью интернет-пользователей. Навскидку, это примерно 2015-2017 гг. Правдоподобную статистику посещаемости можно получить, анализируя логи HTTP-сервера. Главное – не учитывать запросы от пользователей, которые по User-Agent похожи на ботов. Опять же, здесь на помощь приходит Клод. Что же до статистики поисковых запросов, то она доступна в Яндекс.Вебмастере и Google Search Console.
Результат переноса блога находится перед вашими глазами. Я просмотрел все страницы, чтобы убедиться, что нигде ничего не поехало. Также не должны были сломаться внешние ссылки и подписки на RSS. Тем не менее, я мог что-то упустить. Если найдете проблему, прошу сообщить мне о ней.
Помимо прочего, новая версия блога удобна тем, что позволяет использовать иллюстрации большей ширины. Раньше я был ограничен картинками примерно до 512 пикселей в ширину. Что не было чем-то из ряда вон выходящим в 2009-м году, но в 2025-м бывает маловато. Вот, например, скриншот старого сайта на память (кликабельно):
Заметьте, что я начал использовать формат изображений WebP. Его поддержка есть во всех популярных веб-браузерах, выпущенных за последние пять лет. Ранее я использовал только JPEG и PNG. На вид изображения в WebP неотличимы. Зато файлы получаются в несколько раз меньше, или в худшем случае – такими же. Поддерживается сжатие как с потерями, так и без.
Также в отрывках кода теперь я могу использовать строки до 80-и символов в ширину, и это не приводит к появлению горизонтальной прокрутки. Прокрутка плоха тем, что скрывает часть информации. Раньше я был ограничен примерно 70-ю символами. Однако сказанное справедливо лишь для десктопов. На мобильных устройствах ширина экрана меньше. Прокрутка где-нибудь да появится при любой реалистичной ширине строк.
Да, блог наконец-то стал совместим с мобильными устройствами. Старая версия была условно совместима за счет наличия в браузерах reader view. Теперь все нормально выглядит на смартфонах и без него.
Есть и другие изменения, но я думаю, что они мало кому интересны. Как по мне, получилось неплохо. А вы что думаете?