Повторное использование шаблонов

(Из ленты )

Лень — двигатель прогресса

Сегодня мы рассмотрим способ, позволяющий немного упростить себе жизнь
при создании интерактивного сайта путем повторного использования шаблонов. Визуально результат будет примерно таким же, как при дублировании бизнес-логики в браузере, но ценой существенно меньших
трудозатрат на разработку JavaScript-клиента, да и на серверной части
тоже. Хотите узнать как это провернуть?

Небольшая ремарка, чтобы не было недопонимания из-за терминологии:

  • Шаблон(template) : HTML-документ с расширенным набором тегов,
    которые впоследствии используются для подстановки динамических
    данных.
  • Шаблонизатор(templating engine) : библиотека, позволяющая на
    основе шаблона (использующего определенный синтаксис
    дополнительных тегов) и динамических данных получить итоговый
    HTML-документ, пригодный для отображения в браузере.
  • Рендеринг(rendering) : в данном контексте — процесс, которым занимается шаблонизатор.

Общий принцип

Чтобы сразу в голове сложилась нужная картина, начнем с дополненной
схемы из статьи про архитектуру интерактивных сайтов:

Повторное использование шаблонов

Если вкратце, то стандартный интерфейс внутренних сервисов, скрывающихся
за блоком «Бизнес-логика», можно реализовать таким образом, чтобы он
возвращал все необходимые данные для рендеринга шаблона плюс его имя.
База шаблонов у всех общая, у каждого уникальное имя, каждый сервер
интерфейсов (обоих) держит по копии всех шаблонов в памяти.

HTML интерфейс просто разбирает HTTP-запросы, отправляет на его
основе сообщение(ия) внутренним сервисам, получает в ответ имя шаблона и
данные для его заполнения, с помощью шаблонизатора рендерит итоговый
HTML и отдает браузеру или роботу.

Интерфейс сериализованных данных(если он, как и обсуждалось ранее,
работает через постоянное соединение с браузером)
 каждому
подключившемуся клиенту первым делом отправляет
JSON-объект с шаблонами, по крайней мере если их не особо
много, иначе лучше «по запросу». При действии пользователя
JavaScript-клиент отправляет сообщение с информацией, на его основе
интерфейс сериализованных данных передает то же самое (а может и как-то
модифицированное) сообщение внутреннему сервису, также получает в ответ
имя шаблона и данные и перенаправляет их клиенту (возможно
сконвертировав в другой формат). Клиенту остается передать их своему
шаблонизатору и заменить результатом его работы какую-то часть уже
имеющегося в окне браузера HTML-документа.

Рендеринг

Шаблонизаторов сейчас доступно огромное количество под любую
платформу, с разной производительностью и возможностями, но чтобы
воплотить эту стратегию в жизнь подойдут далеко не все. Два основных
требования:

  • Отсутствие внешних вызовов при рендеринге, то есть на входе только
    данные, если используются какие-то фильтры или что-то такое — они
    должны быть частью шаблонизатора.
  • Шаблонизатор должен иметь реализацию на JavaScript, так как будет
    исполняться в том числе и в браузере.

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

В этой схеме напрашивается использование node.js для
реализации HTML-интерфейса, что откроет доступ к многочисленным
шаблонизаторам, реализованным исключительно на JavaScript.
Тем более кроме рендеринга шаблонов эта часть проекта практически ничего
и не делает. В качестве бонуса требование про отсутствие внешних вызовов
станет не таким строгим, да и в целом, если минималистичное решение
вроде mustache по каким-то идеологическим соображениям
не устраивает — любой написанный для node.js шаблонизатор наверняка
станет отличным выходом.

Структура шаблонов

При рендеринге на клиентской стороне обычно нужно заменять лишь
содержимое определенного блока, где располагается основной контент
сайта. Изменения в в других частях сайта нужны существенно реже,
соответственно стоит вынести их в отдельные шаблоны.

Таким образом большинство шаблонов, соответствующих страницам сайта,
представляют собой содержимое одного блока. Отдельные шаблоны,
актуальные для всего сайта, создаются для:

  • Блока <head> документа
  • Видимой «шапки» сайта
  • Сайдбара(ов), если они не сильно зависят от основного контентом
    страниц
  • Видимого «подвала» сайта плюс тегов для подключения
    JavaScript

HTML-интерфейс при чтении их из файловой системы «склеивает» их в
полные шаблоны для каждой страницы, просто конкатенацией или с
использованием механизмов шаблонизатора. Интерфейс сериализованных
данных
«заворачивает» шаблоны страниц в JSON (или другой используемый
формат) прямо в исходном виде для вставки в блок с основным контентом.
Из «общесайтовых» шаблонов браузерному клиенту вероятно могут
понадобиться только сайдбар(ы), и то не всегда.

Изменения в остальных частях сайта лучше все же отдать на совесть
представлений на основе клиентского фреймворка. В первую очередь это
касается изменения <title> и других мета-тегов.

Примечания

  • При использовании минималистичного шаблонизатора без внешних вызовов
    будьте морально готовы передавать ему «многоуровневые» объекты для
    вставки в шаблон. Например, если говорить о постраничной навигации,
    там, где в продвинутом шаблонизаторе было бы что-то вроде {% pagination(current_page, total_pages) %}, может понадобится не
    только написать саму верстку (что, в целом, хорошая практика), а еще
    и передать информацию о точном списке страниц, какая именно из них
    активная, где пропуски и пр.
  • Стоит обращать внимание на производительность используемого
    шаблонизатора. Например, под одну из платформ «официальная»
    реализация mustache, как оказалось, проигрывает сторонней с
    отрывом в 2 порядка.
  • Хоть при таком подходе добиться одинакового внешнего вида страниц
    при рендеринге серверной и клиентской частью достаточно легко,
    следить за их соответствием все же стоит — какие-то детали можно и
    упустить.

Заключение

Как я уже намекал в конце предыдущего материала,
обсуждавшийся в этой статье подход не совсем «идеологически
правильный»
, по крайней мере с точки зрения используемого клиентского
фреймворка
. Модели, вероятно, будут использоваться для хранения
библиотеки шаблонов и данных для их рендеринга, а не для объектов
предметной области проекта. Представления будут отвечать лишь за
рендеринг шаблонов и синхронизацию второстепенных элементов интерфейса.
Если Вы все же пойдете по этому пути, хочется, чтобы Вы сделали это
осознанно. Альтернативный сценарий создания полноценного
JavaScript-приложения для работы в браузере для некоторых проектов
по-прежнему может оказаться более предпочтительным.

В следующей статье мы наконец-то перейдем к более привычной для меня
серверной части интерактивных сайтов, там тоже есть много интересных
моментов, которые стоит обсудить.

Эта статья — четвертая в серии про Интерактивные сайты, автор — Иван Блинков, основано на личном опыте.
До встречи на страницах Insight IT!

Источник: Повторное использование шаблонов