Современный WordPress — это нечто!

Я разочарован тем, во что превратилась разработка WordPress. Если вы не следили за Gutenberg и полным редактированием сайта (FSE), вас может удивить, насколько кардинально изменились современные темы WordPress — и, к сожалению, не в лучшую сторону.

Флагманская тема

Twenty Twenty-Four — это флагманская тема WordPress 2024 года. Она должна служить эталоном современной разработки тем. Так, как это должно быть сделано.

Вот “шаблон” главной страницы для флагманской темы:

<!-- wp:pattern {"slug":"twentytwentyfour/template-home-business"} /-->

Это уже не тот PHP, к которому мы привыкли. Это HTML-файл с единственным комментарием, содержащим JSON? Да. Этот комментарий ссылается на файл в папке patterns/. Указанный файл на самом деле PHP, хотя в нем практически нет кода, только структура.

Давайте разберем его:

<?php
/**
 * Title: Business home template
 * Slug: twentytwentyfour/template-home-business
 * Template Types: front-page, home
 * Viewport width: 1400
 * Inserter: no
 */
?>

<!-- wp:template-part {"slug":"header","area":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","style":{"spacing":{"blockGap":"0","margin":{"top":"0"}}},"layout":{"type":"default"}} -->
<main class="wp-block-group" style="margin-top:0">
  <!-- wp:pattern {"slug":"twentytwentyfour/page-home-business"} /-->
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","area":"footer","tagName":"footer"} /-->

По сути здесь нет PHP. Только комментарии. Файл начинается с комментария PHP, служащего заголовком, а затем идет смесь HTML и тех самых специфичных HTML-JSON комментариев. На этот раз они вложены с закрывающими комментариями, такими как <!-- /wp:group -->.

Давайте рассмотрим стилизацию.

Значение Viewport width: 1400 в заголовке, скорее всего, влияет на визуальное представление. Мы видим JSON-свойства, такие как "margin":{"top":"0"}, которые напоминают CSS. Класс wp-block-group выглядит знакомо — классы удобны для стилизации через CSS, но при этом используется и встроенный стиль: style="margin-top:0".

Вернемся к стилизации позже.

Если вам интересно, что такое HTML-JSON и зачем он нужен, посмотрите мою статью о проблеме Gutenberg в WordPress. Если коротко, это технический обходной путь. Изначально он был создан на основе React, затем распространился на шаблоны, и теперь предполагается, что разработчики должны писать его вручную.

В любом случае, шаблон главной страницы содержит wp:pattern и wp:template-part — предполагаемые включения. Последние напоминают старую функцию get_template_part(). Однако “parts” — это не PHP-шаблоны, а просто HTML-файлы. В итоге, patterns/ содержит PHP, а parts/ — HTML, но по сути оба варианта представляют один и тот же HTML-JSON формат.

Проблемы с базой данных

Как и блоки Gutenberg, HTML-JSON для FSE часто оказывается в базе данных. Можно настроить шаблон заголовка через редактор сайта (FSE):

Настроенные шаблоны сохраняются в базе данных:

Что произойдет, если изменить parts/header.html? Ничего, потому что этот файл не является настоящим шаблоном. Он просто временный контейнер, который может быть загружен в базу данных, но если это произошло — файлы теряют смысл.

Как же редактировать шаблоны последовательно и согласованно?

Вот в этом и проблема — сделать это невозможно без работы с базой данных напрямую.

Шаблона не существует. Нет источника. Наверное нужно использовать SQL REPLACE на HTML-JSON… 🤷

Это снова та же Gutenberg проблема.

Это не самый странный гибрид кода, который вы когда-либо видели? Думаю, большинство разработчиков до сих пор представляют темы WordPress как PHP-шаблоны. К счастью, их можно делать таким образом.

Стилизация

Я уже писал о том, как WordPress нарушает базовые принципы CSS. Я столкнулся с проблемой, которая обсуждается в этом GitHub-треде. WordPress часто называют системой, обеспечивающей обратную совместимость, но это не относится к CSS. Почти каждый релиз WP ломает старый CSS.

В приведенном выше коде флагманской темы мы уже увидели CSS-в-JSON-в-HTML-комментариях-в-PHP-файле. Темы должны иметь style.css в корневом каталоге.

/*
Theme Name: Twenty Twenty-Four
Theme URI: https://wordpress.org/themes/twentytwentyfour/
Author: the WordPress team
[...etc]
*/

Этот CSS-файл обязателен. Но теперь он не используется - это просто еще один заголовок. Этот файл существует по историческим причинам. Возможно, это и стало началом тенденции WordPress класть данные в неправильные форматы файлов. Современная тематика доводит эту тенденцию до абсурда.

Современные темы имеют файл theme.json - это новый тренд. Пример флагманской темы слишком велик, чтобы привести его здесь полностью, но там есть интересные моменты:

{
  "styles": {
	"blocks": {
	  "core/search": {
		"css": "& .wp-block-search__input{border-radius:.33rem}",
		"typography": {
		  "fontSize": "var(--wp--preset--font-size--small)"
		},
		"elements": {
		  "button": {
			"border": {
			  "radius": { "ref": "styles.elements.button.border.radius" }
			}
		  }
		}
	  }
	}
  }
}

Это частичный CSS с использованием & селектора вложенности? Кто родитель? Пока не уверен. Некоторые стили используют пользовательские свойства, а другие имеют жестко закодированные значения. Я даже не могу найти, куда ведет этот "ref".

Где определяется пользовательское свойство --wp--preset--font-size--small? Думаю, в этом массиве, который расположен на три уровня глубже:

{
  "fontSizes": [
	{
	  "fluid": false,
	  "name": "Small",
	  "size": "0.9rem",
	  "slug": "small"
	}
  ]
}

Давайте посмотрим сгенерированный CSS, встроенный в элемент <style>. Я отформатировал его для удобства чтения:

<style>
.wp-block-search .wp-block-search__label,
.wp-block-search .wp-block-search__input,
.wp-block-search .wp-block-search__button {
  font-size: var(--wp--preset--font-size--small);
}
</style>

Итак, .wp-block-search — это родитель, о котором я думал. Если бы только CSS мог поддерживать наследование, некий каскад, вы понимаете? В любом случае, почему здесь используются BEM-подобные имена классов, чтобы только включить родительский класс? Это избыточно и лишено смысла. Возможно, это сделано, чтобы обойти ад специфичности основных стилей блоков.

На данный момент мы видели стили в HTML-JSON “шаблонах” и больше CSS, сгенерированного монстром theme.json. Хотите увидеть еще?

Давайте заглянем в functions.php. Еще один основной файл тем WordPress.

register_block_style(
  'core/list',
  array(
	'name' => 'checkmark-list',
	'label' => __('Checkmark', 'twentytwentyfour'),
	'inline_style' => '
	  ul.is-style-checkmark-list {
		list-style-type: "\2713";
	  }
	  ul.is-style-checkmark-list li {
		padding-inline-start: 1ch;
	  }',
  )
);

CSS-в-PHP. Это что-то новенькое. Это, похоже, обходной путь для решения открытой проблемы. ul в селекторе избыточен при использовании классов. Как мы видели, избыточная специфичность — это отличительная черта CSS WordPress.

Кроме того, стили загружаются через functions.php:

wp_enqueue_block_style(
  'core/button',
  array(
	'handle' => 'twentytwentyfour-button-style-outline',
	'src'    => get_parent_theme_file_uri('assets/css/button-outline.css'),
	'ver'    => wp_get_theme( get_template() )->get('Version'),
	'path'   => get_parent_theme_file_path('assets/css/button-outline.css'),
  )
);

Загружается ли реальный файл стилей? Да, загружается!

.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-text-color, .has-background):hover {
  background-color: var(--wp--preset--color--contrast-2, var(--wp--preset--color--contrast, transparent));
  color: var(--wp--preset--color--base);
  border-color: var(--wp--preset--color--contrast-2, var(--wp--preset--color--contrast, currentColor));
}

Этот код подключает единственный внешний CSS-файл. Почему именно он? Это остается загадкой. О селекторах с избыточной специфичностью больше нечего сказать. Это результат отсутствия стратегии CSS в WordPress.

Подведение итогов хаоса CSS

Итак, подытожим: флагманская тема WordPress содержит:

  • CSS в заголовке
  • CSS в PHP
  • CSS в JSON
  • CSS в HTML-JSON
  • CSS в элементах HTML <style>
  • CSS в атрибутах style HTML
  • CSS во внешних стилевых файлах

Для полного набора нехватает только CSS-в-JS.

Часть этих стилей жестко закодирована, другие — сгенерированы. Некоторые стили существуют в файлах, другие — в базе данных. Объединенный CSS — это запутанный беспорядок, который весь инлайнится на отображаемую страницу. В каком порядке? Кто знает. А затем появляются баги, и вы никогда ни в чем не можете быть уверены.

Мой совет — снова игнорировать все эти новшества и писать старый добрый стилевой файл с разделением обязанностей. WordPress будет сопротивляться, а основные стили заставят вас плакать, но, по крайней мере, у вас есть шанс написать поддерживаемый CSS.

Растерянность

Я просто нахожу всю эту ситуацию озадачивающей. Как WordPress дошел до такого состояния? Современные темы — это странный гибрид кода внутри кода, который невозможно поддерживать. Я задаюсь вопросом: кто разрабатывает темы таким образом? Судя по тому, что я вижу, все остаются на PHP-шаблонах. Я не могу представить себе молодого разработчика, который захочет учить все это новое безумие.

Обновление на 13 мая 2024 года

Ниже продолжение. Ссылка на оригинальную статью https://dbushell.com/2024/05/13/modern-wordpress-an-update/

Мой последний пост в блоге вызвал большой резонанс. Большинство отзывов подтверждают мои переживания и разделяют мою боль. Мне было неприятно писать этот пост, а публиковать его — ещё хуже, но я чувствовал, что это нужно сказать.

Исправления

Контрибьютор ядра WordPress и разработчик тем Джессика Лышчик любезно ответила на Mastodon:

@dbushell Я думаю, здесь есть некоторое недопонимание: ширина Viewport Width в шаблонах относится к предпросмотру при вставке шаблонов и не влияет на фронтенд.

Причина, по которой шаблоны не хранятся в HTML-файлах, а находятся в PHP, заключается в том, что это позволяет переводить строки шаблонов.

Я согласна, что некоторые части можно было бы доработать или лучше продумать.

TT4 служит способом демонстрации того, как можно делать вещи по-разному. Здесь нет правильного или неправильного.

Продолжая:

@dbushell Я работала над TT4 в тех условиях, которые были. Большинство упомянутых вами вещей являются не прямым следствием темы, а результатом архитектуры Gutenberg.

Я очень ценю этот отзыв, учитывая, насколько сильной была моя критика.

Некоторые, например Хендрик Люрсен в Twitter, также поправили меня относительно свойства Viewport Width. В документации говорится:

Viewport Width: ширина вьюпорта <iframe> при предпросмотре шаблона (в пикселях).

В моей оригинальной статье это значение ошибочно описано как связанное напрямую с CSS-стилизацией. Я могу утверждать, что между ними есть сильная связь, но в целях строгости признаю свою ошибку. У меня нет оправданий тому, что я недостаточно исследовал этот вопрос. Однако я не думаю, что это делает неактуальными другие проблемы, которые я поднимал.

Хотя я использовал тему Twenty Twenty-Four в качестве примера, мои проблемы действительно связаны с «основной архитектурой Gutenberg», как говорит Джессика. Оглядываясь назад, я думаю, что недостаточно хорошо объяснил этот момент. Флагманская тема — это только симптом, а не причина. Я считаю, что она плохая, но не вижу, как она могла бы быть лучше. Я искренне верю, что невозможно кодить современный WordPress логичным или поддерживаемым образом. Gutenberg — это хаос, а не фреймворк.

Альтернативы

Я пробовал работать с Gutenberg, честно. Редактор блоков Gutenberg был выпущен в версии 5.0 в декабре 2018 года. Более пяти лет я пробовал. Я начал использовать его с первого дня. Я создал десятки индивидуальных тем WordPress, полностью используя блоковый редактор. Gutenberg — это провальный эксперимент. Основная архитектура WordPress — это сломанная, запутанная, неподдерживаемая система.

Очевидной альтернативой всему этому безумию является использование PHP-шаблонов и плагина Classic Editor для полного отключения Gutenberg. Многие, кто откликнулся на мою статью, сделали это уже давно. Впервые я признал поражение и установил этот плагин на свой последний проект.

Некоторые предложили ClassicPress. Но я беспокоюсь о совместимости плагинов и безопасности. WordPress — это большая цель для хакеров, и я не уверен, что могу доверять форку.

Другие предложили конструкторы тем, такие как Elementor и Bricks. Честно говоря, я ненавижу эти плагины. Я не хочу писать код для проприетарных фреймворков. В них слишком много привязки с неконвертируемым кодом и навыками. В таком случае зачем вообще использовать WordPress?