И так, в прошлый раз я закончил на AsyncTpl. Это XML/Smarty-based шаблонизатор, кроме этого, по сравнению с подобными решениями он умел:

  • Выводить ошибки
  • Работать на сервере и клиенте
  • Имел зачатки data-binding
  • Основан на самописном XML-парсере (очень простом)
  • Был очень быстрым ;]

А дальше я начал всё больше замечать, что XML слишком строг, а главное многословен и чем больше логики в него засовываешь, тем страшнее становиться.

Поэтому я начал смотреть в сторону альтернативного синтаксиса…

Так появился xtpl :]

Да, он похож на Jade/Pug, но давайте по порядку, как же я до этого докатился.

Дело в том, что мне нужен был синтаксис, который можно понять без подготовки и он не должен быть XML-подобный. На ум приходит только одно, любой web-разработчик знаком с CSS и XPath, так почему бы не сделать на его основе синтаксис.

И вот с этой мысли всё и начинается. Достаточно быстро находиться HAML, Jade/Pug и вот вроде бы ответ, но проблема в том, что Pug атрибуты объявляются через input(...)-нотацию, а не [...], а ещё он tab-based, что мне до сих пор кажется спорным, но поддержку добавил и постепенно пробую, как с этим жить.

Ремарка: Про Slim узнал намного позже, он подходит на 80%

Вот с этого момента и начались мои эксперименты, которые продолжаются и по сей день.

И так, как я уже написал выше, синтаксис должен быть понятным, поэтому я его сделал похожим на CSS.

Всё достаточно просто

tagName#id.className.otherClassName[attr="value"][attrBoolean] {
propName: propValue; // значение всегда JS выражение
on-eventName: ctx.handleClick(); // Вызов функции
// Вложенный тег, если имя не заданно, то по умолчанию div
.headerClassName | Wow, text!
// Вложенный ui-блок (компонент)
&blockName {
x-attrName: "...";

// Вложенный контент
input.text[type="text"] { }
}
}

UI-Блоки определялись прямо в шаблоне

&blockName = label {
class.someName: ctx.expression;
// Место для вставки внешнего контента (slot)
x-content {}
}

Ещё была поддержка директив

form.b-form[action="{ctx.action}"] {
x-derectiveName: {...ctx.options}
// ...
}

Собственно всё. Основной момент был в том, что xtpl продолжал работать как строковой шаблонизатор (подробнее), но после первичного рендера сканировал полученную DOM-структуру и связывал ноды с данными, на основе которых они построить, чтобы получить точечный биндинг.

Да, звучит как изоморфный рендер (когда ещё это не было мейнстримом ;]), но я тогда об этом не думал и в какой-то момент это стало слишком сложно и я решил отбросить серверный рендер.

IDE

Свой синтаксис это круто, только вот без поддержки IDE, это всё нахрен не нужно, как и шаблонизатор без вывода ошибок. Поэтому я упоролся окончательно и написал plugin для подсветки и автокомплита кода в WebStorm.

Ох, то ещё было приключение.

Кроме стандартных решений в стиле Pug/Jade, есть и отличия, например xtpl поддерживал ещё и

  • .foo > b.bar | …<div class="foo><b class="bar">...</b></div>
  • .ico + .ico<div class="icon"></div><div class="icon"></div>
  • b.cbx > b.&__mark<b class="cbx"><b class="cbx__mark"></b></b>

Такие конструкции не только позволяют писать максимально компактный код, но и в купе с подсветкой IDE дают максимально низкий порог входа в подобный новодел. Достаточно сказать разработчику, что это CSS-like синтаксис и вопросов будет минимально.

Всё это не голословные утверждения, в отличии от AsyncTpl, xtpl нашел своё применение.

Таким проектом стал Рестордер, который увы и ах, не «взлетел».

Это была b2b площадка для Поставщиков и Ресторанов, но главное, это был Single Page Application с xtpl на борту и удаленным верстальщиком в команде (я отвечал за архитектуру в целом и js конечно). И как показал этот опыт, человек без опыта работы с подобными шаблонизаторами смог спокойно верстать без лишних вопросов.

Самое удивительное в этом всём, что проблемы конечно были, но минимальные, вывод из этого один, пишите тесты, больше и чаще. Никогда не гнушайтесь проверить граничные и заведомо ошибочные или невозможные сценарии, рано или поздно, они произойдут ;]

На этом всё, ещё раз оставлю ссылку на слайды с xtpl и уже перейду к Exility :]

⟵ Часть I: Шаблонизаторы. / Skeletik ⟶

--

--