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

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

 

Сегодня мы рассмотрим способ, позволяющий немного упростить себе жизнь при создании интерактивного сайта путем повторного использования шаблонов. Визуально результат будет примерно таким же, как при дублировании бизнес-логики в браузере, но ценой существенно меньших трудозатрат на разработку 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-приложения для работы в браузере для некоторых проектов по-прежнему может оказаться более предпочтительным.

www.insight-it.ru/programmirovanie/javascript/povtornoe-ispolzovanie-shablonov/

Вверх