Возможна ли жизнь без шаблонизатора?

в 17:33, , рубрики: cmf, cms, html, webcomponents, Веб-разработка

Правильный ответ — да, легко!

Практически всегда описывая устройство CleverStyle CMS у кого-то возникал вопрос, а как же настраивать внешний вид, ведь нет никаких шаблонов.
Нужно признаться, я немного лукавил, говоря что внешний вид можно изменить с помощью CSS. Изменить то можно, но не кардинально.
Шаблонизатора как не было, так и нет, и даже не планируется. Вместо этого для генерации простого HTML используется BananaHTML, а сам интерфейс ложится на плечи Веб-Компонентов и Polymer в частности.

Как я докатился до такой жизни

Шаблонизаторы по разным причинам мне не нравились всегда. В связи с этим в CleverStyle CMS есть понятие темы оформления, которая отвечает за общий облик сайта, но нет шаблонов отдельных страниц.
Во-первых если делать шаблоны отдельных страниц — вы не будете поддерживать всевозможные модули созданные сторонними разработчиками, потому будут использоваться стандартные шаблоны.
Во-вторых шаблоны не позволяют так легко наследовать, и при этом радикально менять внешний вид при необходимости (об этом речь далее).

Первоклассная поддержка Веб-Компонентов

Веб-Компоненты появились не так давно, и есть достаточно много нюансов с их использованием, тем не менее, их удалось решить.
В связи с этим изначально было потрачено достаточно много времени на то, чтобы понять кто виноват — я, как разработчик, полифиллы, или вообще сторонние библиотеки.
Оказалось, что периодически были виноваты все.
В текущей версии CleverStyle CMS, наверное, самая надежная и в связи с этим удобная среда для использования веб компонентов.
В поставку (на момент написания статьи) входят патченные версии:

  • jQuery: исправлено поведение $.fn.offset() для элементов внутри теневого дерева (pull request), исправляет работу всплывающих подсказок и целой кучи других jQuery плагинов
  • WebComponents.js: исправлена обработка относительных путей в css файлах при наличии <base> (pull request)
  • UIkit: модифицированы стили для работы внутри теневого дерева (Скрипт для конвертации, подходит к любым стилям)
  • Polymer: патч, позволяющий наследовать компоненты с теми же именами (обсуждение)

В общем, поддержка Веб-Компонентов из коробки весьма основательная, но вся суть этого поста будет в последней модификации.

Наследовать Веб-Компоненты с теми же именами

Это не исправление проблем совместимости или багов, в отличии от остальных патчей, а новая полезная функциональность.
Выглядит в целом так:

<polymer-element name="test-element" extends="test-element">
    <template></template>
    <script>
        Polymer("test-element", {
            ready : function () {
                this.parent_method();
            }
        });
    </script>
</polymer-element>
<polymer-element name="test-element">
    <template></template>
    <script>
        Polymer("test-element", {
            parent_method : function () {
                alert("I'm your parent!")
            }
        });
    </script>
</polymer-element>

С первого взгляда, возможно, не очевидно, но это позволяет вам создавать интерфейсы исключительно из Веб-Компонентов, а потом наследовать и переопределять их при необходимости.

Как это работало раньше: без патча вы можете наследовать существующие пользовательские элементы (Custom Elements) или элементы самого браузера, но не можете переопределить уже зарегистрированные элементы, с ним же вы можете унаследовать элементы, которые будут объявлены позже, таким образом сохраняя нужное имя элемента.

Для чего всё это?

Создавая элементы интерфейса в виде Веб-Компонентов вы полагаетесь на определённые имена тэгов, и было бы очень удобно, если бы вы могли патчить их на лету.
Так как Polymer является всего лишь оберткой, мы можем откладывать регистрацию элементов до появления наследуемого элемента а так же переименовывать его во избежание конфликтов.
Как следствие можно менять представление совершенно без ограничений, не изменяя начальный код, всего лишь наследуя и модифицируя веб-компоненты.
Таким образом вы можете перевернуть страницу вверх ногами, добавить сторонний виджет комментирования, догрузить данные, которых не было в верстке изначально через API и показать пользователю именно то, что вы хотели.

В контексте CleverStyle CMS

Изачально это было придумано и реализовано для CleverStyle CMS (подробнее в документации), но при желании использования в своих проектах соберите Polymer из этой ветки.
В рамках CleverStyle CMS есть понятие зависимостей между компонентами. Предположим, у вас есть модуль магазина (весьма реальный пример, разработка ведется в отдельной ветке), интерфейс сделан с использованием Веб-Компонентов и вы хотите изменить страницу отображения товара.

meta.json модуля Shop:

{
	"package"		: "Shop",
	"category"		: "modules",
	"version"		: "0.88.1+build-118",
	"description"	: "Shop functionality",
	"author"		: "Nazar Mokrynskyi",
	"website"		: "cleverstyle.org/cms",
	"license"		: "MIT License",
	"db_support"	: [
		"MySQLi"
	],
	"provide"		: "shop",
	"require"		: [
		"System=>1.13",
		"fotorama"
	],
	"optional"		: [
		"Comments",
		"Plupload",
		"TinyMCE",
		"file_upload",
		"editor",
		"simple_editor",
		"inline_editor",
		"payment"
	],
	"multilingual"	: [
		"interface",
		"content"
	],
	"languages"		: [
		"English",
		"Русский",
		"Українська"
	]
}

Компонент может зависеть от чего-то, конфликтовать, и сам предоставлять некоторую функциональность, необходимую другим компонентам, всё это отражается в порядке подключении JS/CSS/HTML файлов компонентов (а нам нужно подключить хакнутую версию перед оригинальной).
Но тут возникает один нюанс, в CleverStyle CMS не может быть двух компонентов, которые предоставляют одну и ту же функциональность, они будут конфликтовать, с другой стороны множественные патчи Веб-Компонентов (методом, описанным выше) разрешены.
Здесь приходит на выручку фича, появившаяся в версии 1.17, которая позволяет указать, что это не самостоятельная функциональность, а расширение функциональности другого компонента:

{
	"package"		: "Shop_item",
	"category"		: "modules",
	"version"		: "0.0.1+build-1",
	"description"	: "Shop item hack",
	"author"		: "Nazar Mokrynskyi",
	"license"		: "MIT License",
	"provide"		: "shop/item"
}

Именно provide: shop/item показывает что происходит расширение функциональности shop, подробнее о зависимостях и конфликтах.

После этого можно объявлять в Shop_item наследование отображения товара:

<polymer-element name="cs-shop-item" extends="cs-shop-item">
    <!--А здесь уже что вам угодно-->
</polymer-element>

При этом исходный код страницы с товаром не меняется и выглядит весьма дружелюбно для поисковых систем (а учитивая минимальность кода даже очень):

<section data-date="0" data-id="1" data-in_stock="24" data-price="20" data-soon="0" is="cs-shop-item">
	<div id="images">
		<img alt="" src="http://cscms.org/storage/public/Plupload/2015-01-03/18/2_031854a812c6b264b.jpg">
		<img alt="" src="http://cscms.org/storage/public/Plupload/2015-01-03/18/2_035654a812ec26d24.jpg">
		<img alt="" src="http://cscms.org/storage/public/Plupload/2015-01-03/18/2_035654a812ec1c834.jpg">
	</div>
	<div id="videos">
		<a href="https://www.youtube.com/watch?v=rHBxJCq99jA"> </a>
		<a href="https://www.youtube.com/watch?v=bmtbg5b7_Aw"> </a>
	</div>
	<h1>Boots</h1>
	<div id="description">
		<p>Nice boots</p>
	</div>
	<div id="attributes">
		<table>
			<tr>
				<td>Size</td>
				<td>2</td>
			</tr>
		</table>
	</div>
</section>

Заключение

Используете вы CleverStyle CMS или нет, все патчи открыты и доступны, так что я рекомендую всем попробовать и выразить свое мнение в комментариях.
За Веб-Компонентами будущее!

Автор: nazarpc

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js