Заранее думать о масштабировании, по максимуму использовать стандартные решения Wordpress, сделать тему WP своими руками, заботиться об удобстве верстальщика, упороться по мобильности — и обновить блог компании так, чтобы его любили читатели, редакция и руководство. У нас получилось.
Блогу компании Promopult уже 9 лет. За это время он пережил несколько трансформаций. О последней рассказывает Сергей Глазов, технолог нашего блога и других важных штук в системе Promopult.
Это уже не обсуждается, ибо стало нормой: быстрый и простой стандарт для блога компании, персоны, личного, да вообще, какого угодно — WordPress. Можно поспорить, но факт остается фактом.
Хочу рассказать о том, к чему я пришёл в плане организации кода, работы с WordPress-блогом и его поддержкой. Эта история — про процесс, потому что текущее состояние — последняя точка в этом процессе и кажется, именно текущее состояние наиболее удачное по сравнению со всеми прошлыми итерациями в подходах к организации.
Первые задачи: мобилизация и дизайн
Как было у нас с работой над кодом
Что хотелось получить, как говорится, «в идеальном мире»
Редизайн, первый подход
Второй подход: новый вариант структуры
Блог PromoPult: как все устроено
Чек-лист перед публикацией
Настройки поста в админке блога
Приятные мелочи
Про интересное техническое
Какие плагины используем
Советы-выводы для тех, кто работает на блогом компании
Что было на (моем) старте — в 2016 году
Редко когда разработчик создает и продумывает всё с нуля. Чаще же получается так, что уже (чаще даже — давно, с отдельной историей) есть проект, который нужно поддерживать. Редизайн, правки, огромные ТЗ и требования. И в условиях существующего всего нужно как-то оперативно ориентироваться и решать задачи.
Я принял блог в 2016 году, когда у него уже была длинная история и не все так прекрасно, как хотелось.
- Старый дизайн блога с девятилетней историей.
- Отсутствие мобильной/планшетной версии в каком-либо виде.
- Больше 600 постов.
- Структурные проблемы с контентом и его организацией: 20+ категорий и девять с лишним сотен тегов (сейчас больше, но мы уже остановились).
- В планах уже есть ребрендинг и переезд на новый домен. Блога это тоже касается.
- Длинная цепочка действий при работе с кодом.
- Работа без контроля версий (.git).
Первые задачи: мобилизация и дизайн
Первостепенной задачей было добавить в существующую тему блога адаптивности: сделать так, чтобы мобильные пользователи могли адекватно читать посты и пользоваться сайтом — про Mobile First говорили и писали все чаще, да и статистика показывала, что блог читают с мобильных.
Параллельно с этими работами рисовался новый дизайн.
Я как разработчик работал в паре с дизайнером, без лишней цепочки посредников в обсуждении, так что процесс коммуникации был быстрее и живее. Очевидный факт, конечно, но почему-то в многих процессах им пренебрегают. И получается так, что дизайнер делает что-то сильно оторванное от реальности. Разговаривайте ртом и обсуждайте все моменты. Каждый участник процесса заинтересован сделать хорошо и круто. Но не каждый понимает, что процесс — связанная цепочка, и если отдельный исполнитель на своем участке работ что-то упустит или не сделает — следующим в процессе людям будет тяжело.
По ходу работы над мобильной версией я увидел минусы и слабые места организации процесса разработки. Хотелось ускорить и упростить всё.
Как было у нас с работой над кодом в блоге
Существовала DEV-версия блога с отдельной тест-базой данных. Работа с файлами происходила на удалённом сервере, тестирование проходило по отдельному адресу, недоступному во внешнем мире. После работы, тестирования и рождения какой-то единицы смысла — она выкатывалась на боевой блог через обращение к админу. Что делал он — отдельная магия.
Для блога, где что-то меняется один раз за год, — отличный процесс. Но с новой редакцией и её потребностями такой процесс был бы большой болью.
Что хотелось получить, как говорится, «в идеальном мире»
Весь код лежит в .git-репозитории. Боевой вариант блога — master
-ветка этого репозитория. Вся работа с кодом происходит через коммиты в dev
-ветку или другие ветки, связанные с отдельными большими задачами.
После того, как задача сделана — создаётся Pull Request (PR) и/или Merge Request (MR) с набором правок. Смысл в MR b PR один и тот же, но в разных сервисах — разное название. У нас GitLab, поэтому — Merge Request.
При создании MR становится доступным временный адрес вида имя-git-ветки-test.dev.blog.promopult.ru
, доступный только по IP для живой проверки на тест-окружении.
Код в созданном MR ревьюится и проверяется в автоматическом (линтеры кода, которые проверяю синтаксис по заранее определенным правилами) и в ручном режиме (вертикаль власти в команде, на всё пристально смотрит своим военно-морским выпуклым внимательным глазом тимлид). После прохождения ревью — из интерфейса браузера .git-репозитория нажимается кнопка «Merge» и все изменения появляются в эфире боевого блога через какой-то краткий очевидный промежуток времени.
Редизайн, первый подход
План работ по редизайну блога:
- Вёрстка статичного прототипа по дизайн-макетам всех страниц;
- Превращение («натяжка») вёрстки в WordPress-тему.
Вёрстка — отдельный этап работ. Для удобной работы со стилями (CSS), разметкой и JS в проекте был использован набор плагинов и модулей, который собирается через Gulp-задачи, описанные в сборщике SPT (Start Project Template).
Ключевые слова, которые используется в сборщике статичной темы блога: HTML, CSS, JS, Babel, Gulp, PostCSS, SCSS, Nunjucks.
По завершению работы над вёрсткой структура была такой (указаны только каталоги первого уровня):
+-- design # Дизайн, макеты и всякое +-- app/ # Исходники проекта: отдельные модули +-- dist/ # Собранный вариант проекта (html-файлы) и вся статика +-- gulpfile.js/ # Конфиг Gulp.js L-- package.json # Файл-конфиг сборщика: пакеты, скрипты
Каждый отдельный визуальный смысловой элемент на странице, например, карточка поста (/components/article_card/
), представлял из себя папку, в которой был:
— файл разметки (article_card.html
),
— файл стилей (article_card.scss
),
— файл JS (article_card.js
).
И каждая страница собиралась из таких отдельных блоков-компонент. Блоками удобно манипулировать, а любые изменения не затрагивают соседние элементы.
На выходе сборщик создавал папку dist
, в которой содержались готовые html-файлы страниц для наглядного просмотра в браузере на этапе правок и согласований, а также один файл стилей все темы и два JS-файла: один файл (app.js
) описывал логику и поведение сайта, второй (vendor.js
) содержал все библиотеки, используемые для сайта (jQuery, fotorama, magnific-popup и другие).
Дальше всё это нужно превратить в WordPress-тему и продумать файловую структуру. Чтобы можно было удобно работать со статичной вёрсткой и рядом же лежала WP-тема.
Список макетов, которые приготовил дизайнер. Они совпадают с файлами WordPress-темы блога:
- Главная страница (файл
home.php
). - Страница отдельной записи/поста (
single.php
). - Вид отдельной текстовой страницы (
page.php
). - Страница подписки на рассылку (
subscribe.php
). - Ошибка 404 (
404.php
). - Отдельная страница тега (
tag.php
). - Отдельная страница категории (
category.php
). - Поиск и результаты поиска (
search.php
).
Рабочий процесс с таким подходом и разделением на статичный вариант и WordPress-вариант темы происходит так: если нужно что-то поправить в визуальной части — правки вносятся в статичном варианте и после теста переносятся в тему. Если правки нужны в какой-то не визуальной части — то изменяются только файлы WP-темы.
Папка с темой блога — bsp
. Она расположена по пути в папке с темами самого блога:
+-- wp-content/ # Пользовательские файлы WordPress-сайта ¦ +-- themes/ # Темы сайта ¦ ¦ +-- app/ # Исходники статичной темы ¦ ¦ ¦ +-- gulpfile.js/ # Gulp-задачи для сборки ¦ ¦ +-- dist/ # Сборка статичной темы ¦ ¦ ¦ +-- assets/ # Ресурсы: JS, CSS и графика ¦ ¦ +-- bsp/ # WP-Тема блога PromoPult ¦ ¦ ¦ +-- assets/ # Ресурсы: JS, CSS и графика, копирование из `/dist/` ¦ ¦ ¦ +-- home.php # Главная страница блога и другие файлы в корне темы
Место wordpress-темы очевидно и предопределено файловой структурой самого WordPress.
Других тем в директории с темами нет — всё стандартное удалено. Есть миф о повышении производительности таким образом, но мы этого не заметили. Это сделано скорее для порядка в коде. Не нужно хранить то, что не используется и точно не будет использовано.
Также в .git лежат и все WP-плагины, которые используются. На нашем сайте это — Google XML Sitemaps, RSS for Yandex Turbo, RusToLat и WP-PostViews.
Статичный, свёрстанный прототип страниц блога и файлы-исходники были перемещены в директорию темы блога: чтобы взаимодействовать было удобно и с логической частью шаблона и со всем тем, что отвечает за внешний вид и поведение элементов на странице.
Статичный вариант сборки проекта — с исходниками и всеми зависимостями в первой попытке организации структуры — был помещен в директорию тем.
То есть рядом с основной темой bsp
добавилась директория /app
, в которой размещены исходники вёрстки темы и gulp-сборщик. Но в таком варианте был один сложный момент: статичные файлы генерировались в отдельную директорию, и чтобы изменения были в WP-теме, нужно было копировать статичные файлы стилей и скриптов в папку assets
внутри темы.
Второй подход: новый вариант структуры
В первые недели это было решено простым консольным скриптом, которые копировал собранные файлы из статичной темы в WP-тему. Лишнее действие влечёт к ошибкам. Поэтому вариант был только в исправлении структуры.
У нас есть три важных директории (все пути от корня):
- WP-тема:
/wp-content/themes/bsp
- Исходники статичной темы:
/app
- Собранная статичная тема:
/dist
А внутри неё — assets
с файлами стилей, графикой и JS
Нужно расположить всё так, чтобы файлы статики стилей и скриптов собрались в нужную папку (/wp-content/themes/bsp/assets
).
Новый вариант структуры оказался таким:
+-- gulpfile.js/ # Gulp-задачи для сборки +-- wp-content/ # Пользовательские файлы WordPress-сайта ¦ +-- plugins/ # WP-плагины ¦ +-- themes/ # Темы сайта ¦ ¦ +-- bsp/ # Тема блога PromoPult ¦ ¦ ¦ +-- app/ # Исходники статичной темы ¦ ¦ ¦ +-- assets/ # Ресурсы: JS, CSS и графика (автогенерация) ¦ ¦ ¦ +-- home.php # Главная страница блога и другие файлы в корне темы +-- wp-admin/ # WP-файлы для админки +-- wp-includes/ # WP-файлы системы
В корне всего проекта лежат gulp-задачи — и исполняются из корня. В конфиге gulp-задач описана структура, что статичные файлы собираются из директории wp-content/themes/bsp/app
в wp-content/themes/bsp/assets
без каких-то дополнительных действий типа копирования и т.п.
Файлы WP-темы остаются без изменений и работа происходит по старому сценарию: правки в статике > перенос в WP-файлы. Статика CSS и JS генерируется сразу в папке с темой и всё просто работает.
Всё это было про процесс работы. Теперь про то, как устроен сам блог.
Блог PromoPult: как всё устроено
Самая главная сила блога — команда. Редактор, авторы, верстальщики.
Большая задача — сделать работу с контентом блога удобной в админке. А с учётом того, что тема нашего блога сделана специально под задачи контента и запросы редакции — админка была доработана соответствующим образом.
Чек-лист перед публикацией
Любую работу важно контролировать. Вёрстка статьи — стандартный, формализованный процесс, который спокойно можно представить в виде чек-листа.
Идею увидели у ребят из EmailSoldiers. Решили применить у себя.
Если какой-то пункт не отмечен — система предупредит перед публикацией.
По клику на ссылки, подчеркнутые ссылки в элементе списка — подсвечиваем конкретный пункт.
Чек-лист составлен в том же порядке, что и дополнительные настройки поста в админке.
Настройки поста в админке блога
Тесно переплетены с чек-листом публикации, описанным выше.
При разработке темы я старался не использовать плагины, а сделать простое и лёгкое решение для задач темы. Основные моменты:
- Описания для SEO-мета тегов.
- Описания для OpenGraph-тегов, которые используют соцсети при расшаривании материала и формируют симпатичные карточки статей.
- Удобная работа с картинками-обложками для постов. Одна картинка обязательна — она добавляется в карточку поста в плитке публикаций, которая отображается на главной и на странице рубрики или тега.
- Дополнительные настройки темы: пост может быть с обложкой или без, есть краткий текст-анонс, который мы показываем в шапке с обложкой, и он же используется в описании статьи в рассылке дайджеста.
Раздел настроек поста реализован через мета-боксы и пользовательские поля в WordPress.
Через мета-бокс добавлен и чек-лист публикации.
В шаблонах работа с полями устроена просто: если поле не пустое и заполнено — достаем значение и показываем. Например, вот так выводится блок-реакция на пост:
<?php if (get_post_meta($post->ID, 'postreaction', true)) { ?>
<div class="article_reaction">
<div class="label-reaction"><span><?php echo get_post_meta($post->ID, 'postreaction', true); ?></span></div>
</div><!-- /.article_reaction -->
<?php } ?>
Пример вывода реакции на карточке поста:
Приятные мелочи
Есть несколько приятных мелочей, которые, может быть, никто и не видит. Но если кто-то заметил — хорошо.
Например, даты публикации поста в карточках и в отдельном посте у нас в кириллице и умеют склоняться. Почему-то этого нет в коробке WordPress. Если дата публикации в текущем году, то год у нас не показывается, если год отличается от текущего — дата показывается вместе с годом публикации.
Счётчик комментариев поста. Долго спорили о том, что «0 комментариев» или «нет комментариев» очень смущает. Решение очень простое: не показывать счётчик комментариев вообще, если комментариев меньше одного.
В целом, над системой комментариев мы работаем отдельно и хочется поговорить об этом в рамках отдельного большого поста. Мы делаем простую и удобную систему комментариев с простой авторизацией через соцсети.
Свои собственные лайки: комментирование или расшаривание ссылки в соцсетях — долгое дело по меркам темпа потребления контента, а вот жмакнуть «лайк» и дать понять, что статья клёвая — просто и быстро. Мы сделали свои простые лайки и вывели счётчик в карточку поста. И лайки прибывают довольно быстро. А так как они стоят внизу статьи — это еще и сигнал, что текст дочитали.
Сделали тёмную тему для своего блога — нынче модно такое. С учётом модульной структуры (по сути сайт — набор блоков, которые как-то между собой комбинируются) и организации стилей получилось сделать довольно быстро.
Про интересное техническое
В теме есть минификация кода разметки, CSS и JS. CSS и JS сжимается через gulp-задачи в сборщике статики, а вот минификация разметки сделана через WordPress-хук WP_HTML_Compression
.
А в комментарии в разметке мы добавили промокод для тех, кому интересно, как устроен сайт изнутри и кто первым делом идёт смотреть исходный код:
Кэширование CSS и JS. Чтобы файлы стилей и скриптов кэшировались, но всегда были актуальными, если мы что-то переделали — используем filemtime(). Многие в таком случае используют ?<?php echo time(); ?>
. Но такой вариант загружает файл и делает запрос при каждом обращении.
Лучше использовать такой трюк:
<link rel="stylesheet" type="text/css" href="<?php echo get_template_directory_uri(); ?>/assets/styles/style.css?t=<?php echo filemtime(get_theme_file_path().'/assets/styles/style.css'); ?>" />
В таком случае файлы будут загружаться, если они были изменены, и в параметр запроса будут добавлена дата изменения файла.
Какие плагины используем
Несмотря на возможность и желание в некоторых случаях обойтись своим решением, плагины всё же мы используем. Список у нас такой:
- Google XML Sitemaps — для генерации XML-карты сайта для роботов;
- RSS for Yandex Turbo — турбо-страницы для Яндекса;
- RusToLat — транслитерация русских символов URL в английские;
- WP-PostViews — считает просмотры материалов;
- Classic Editor — включает классический WordPress-редактор вместо нового блочного Gutenberg;
- Ограничение попыток авторизации — это для безопасности: при нескольких ошибочных попытках логина — баним входящего на настраиваемый промежуток времени;
- AMP — AMP-страницы для Google.
Советы-выводы для тех, кто работает над блогом компании
- Советую в начале работы над проектом сразу думать о масштабировании.
- Обязательно использовать
.git
в работе. Для 2019 года, конечно, странный совет, но этот совет может спасти кого-то от седых волос и выговора, когда что-то пойдет не так. - Разработку и работу над WordPress-темой лучше разделить на два этапа: сначала верстать что-то статичное, а уже свёрстанное «натягивать» как тему на WordPress.
- Если есть возможность — время, команда и понимание того, зачем вам всё это, — делайте тему сами, без использования готовых вариантов. Выиграете в порядке и понимании того, как всё устроено. Не будете плодить костыли.
- Используйте стандартные хуки и возможности WordPress, если ваш блог построен на нём. Кастомизировать и сделать удобное решение можно быстро и просто.
- Делайте удобно для пользователя и редакции.
- Не забывайте про социальные сети и микроразметку.
- Не забывайте про мобильные версии.
- Не забывайте про регулярные обновления плагинов и системы.
- Выбирайте только проверенные плагины.
Работа над блогом продолжается — оставайтесь с нами.
Комментарии (18)
mihdan
27.06.2019 17:13Например, даты публикации поста в карточках и в отдельном посте у нас в кириллице и умеют склоняться. Почему-то этого нет в коробке WordPress
В ядре есть date_i18n(), которая и занимается этим.PromoPult Автор
01.07.2019 13:06Спасибо! Есть повод переписать то, что есть у нас.
Если кому-то тоже интересно, то начать можно с этого: developer.wordpress.org/reference/functions/date_i18n и/или wp-kama.ru/function/date_i18n
monochromer
27.06.2019 21:07Лучше использовать такой трюк:
Наверно, хотели написать
<link rel="stylesheet" type="text/css" href="<?php echo get_template_directory_uri(); ?>/assets/styles/style.css?<?php echo time(); ?>" />
filemtime()
вместоtime()
?PromoPult Автор
27.06.2019 21:37Да, при верстке использовали не тот пример кода. Спасибо, что указали на ошибку.
m0ze
27.06.2019 21:38Спасибо, было интересно почитать. Жаль только, что вы не затронули вопросы нагрузки, самого WordPress'а версии 5+ и все возможные его косяки «из коробки» конкретно в вашем проекте, если что-то «выпиливали» из стандартного функционала, то что именно и почему, какой под этот блог выбрали хостинг и пр.
При разработке темы я старался не использовать плагины, а сделать простое и лёгкое решение для задач темы.
Многие разработчики на этом пункте с вами категорически не согласятся и заведут песню про «тема — только для оформления, плагины — только для расширения функционала» (звонок для учителей,пена для бритья), хотя лично я с вами солидарен.
Плюс, вижу, вы не спешите обновляться с версии 5.1.1 до 5.2.2 (хотя уже в 5.2 закрывается ряд уязвимостей) — почему?
Ещё у вас страницы с записями авторов немного странно выглядят blog.promopult.ru/author/admin :)PromoPult Автор
28.06.2019 12:54> Ещё у вас страницы с записями авторов немного странно выглядят blog.promopult.ru/author/admin :)
Уже поправили, спасибо:)
2. Насчет обновления версии Wordpress: обновляться до 5.2 мы планируем в ближайшее время (основные уязвимости ветки 5.1 исправлены в 5.1.1).VolCh
29.06.2019 20:13Кстати, как с таким подходом обновления проходят? Вы же сам вордпресс в репозитории храните?
PromoPult Автор
30.06.2019 11:58Да, сам WordPress и всё связанно с ним (без пользовательских медиа-файлов) хранится в репозитории. Это накладывает определённые особенности на процесс обновления, но в целом всё это — ручное обновление версии WP: wordpress.org/support/article/updating-wordpress/#manual-update
На ревью--ветке всё тестируется и в не пиковые часы (ночь любого выходного дня) по посещаемости, выкатывается.
Скоро как раз новое обновление ставить.
PromoPult Автор
01.07.2019 13:10«тема — только для оформления, плагины — только для расширения функционала»
Вот тут тоже хочется отметить, что многие плагины реально засоряют код, а при большом количестве таких плагинов будет полный бардак.
Стараемся делать аккуратно и хорошо с теми идеями, которые закладывались при разработке темы. Но иногда плагины — тоже хорошо. Конечно, зависит от задачи.
Спасибо вам за солидарность.
Про нагрузку, хостинг и всякое такое — кажется, что тема отдельной публикации. Пока рассмотрели только вопрос с организацией кода для темы.
vlad-yermolayev
30.06.2019 11:57Расскажите пожалуйста где Вы храните БД? Например для того, чтобы поднять такую же копию как на продакшене мы берем файлы c master, а как быть с БД?
PromoPult Автор
01.07.2019 13:12БД живёт своей жизнью. БД, как и всё на сервере регулярно бэкапится. Если нужно что-то где-то развернуть — берётся свежий дамп базы.
Заботится о копиях БД для использования нужно, если проекты на WP идут потоком, как в студиях. У нас такого кейса просто нет. Поднимается БД, блог, настраиваются бэкапы и начинается работа уже с кодом, через git.
mihdan
Вместо RusToLat пора давно использовать Cyr2Lat.
PromoPult Автор
Вы ведь есть среди авторов плагина Cyr2Lat. Расскажите, пожалуйста, чем они отличаются и почему именно нужно использовать Cyr2Lat?
mihdan
— Поддержка PHP 5.6 — 7.4
— Поддержка новый версий WordPress 5+
— Страница настроек в админке.
— Изменение таблиц траслитераций в админке или по хуку
— Работа с ACF, WPML и еще несколькими популярными плагинами
— Фоновые задачи конвертации (актуально если на сайте больше 10к записей)
— Интерфейс конвертации для WP-CLI
— Исправление более 30 ошибок старых форков
— 100% покрытие тестами
— ООП интерфейс
Ну и много-много улучшений, которые остались под капотом и которые можно видеть в ченджлоге.
PromoPult Автор
А если прям сейчас заменить RusToLat на Cyr2Lat — какие проблемы могут всплыть?
mihdan
Проблем быть НЕ должно, так как сейчас cyr2lat при установке ничего не делает, чтобы не ломать чужие урлы, как это делают форки.
Единственное что может быть — некоторые буквы в RusToLat НЕ соответствовали ГОСТ, а в cyr2lat они по ГОСТ, поэтому могут быть отличие в буквах Ё, Й, Я, Ш, Щ.
Сайт при этом сломаться не должен.