Перевод статьи «Choosing a Templating System», автор Perrin HarkinsВступлениеДавайте, признайтесь: вы написали шаблонизатор. Это нормально, почти у каждого была такая цель. Вы начали с чего-то очень простого, вроде $HTML =~ s/\$(\w+)/${$1}/g и продолжали, добавляя условия, циклы и инклуды, пока вы не создали нерасширяемого монстра. К счастью для вас, вы не первый, кто подумал о том, что это может быть неплохим решением, вынести HTML из своего кода. Многие с этим сталкивались ранее, а некоторые выложили результаты своей работы в CPAN. К настоящему времени, существует так много модулей шаблонизаторов на CPAN, что вы почти наверняка сможете найти тот, который будет удовлетворять ваши потребности. Эта статья послужит вам гидом к этим модулям, ведя вас к цели найти шаблонизатор вашей мечты. А если вы сразу отправились прямо на CPAN, не заморачиваясь на написание собственного, поздравляю: вы на шаг опередили многих из нас. Примечание автора Ничто не вызывает столько споров в рассылке mod_perl, как сообщение о том, что один подход к шаблонам лучше, чем другой. Люди привыкают к выбранным инструментам. Поэтому, вначале следует сказать, что я необъективен. Я занимался изучением этого вопроса долгое время и у меня есть мнение о том, что работает лучше. В этой статье я попытался предоставить объективную оценку возможностей разных шаблонизаторов, но скорее всего, у вас не займет много времени определить то, что мне нравится. Кроме того, попытки быть абсолютно объективным ведут к бесполезным руководствам, которые не содержат никакой полезной информации. Так что примите это все с пудом соли, и если вы считаете, что я был несправедлив к определенному шаблонизатору, допустив ошибку или недочет, дайте мне знать. Зачем использовать шаблоны?Зачем вообще использовать шаблоны? Выражения print и CGI.pm были достаточно хороши для дедушек, так зачем заморачиваться, изучая новые способы сделать то же самое? Единство представления Не надо быть гением, чтобы понять, что сделать шаблон одного меню навигации и использовать его на всех страницах проще в управлении, чем вбивать его везде вручную. Если вы построите весь свой сайт подобным образом, будет гораздо проще производить широкомасштабные изменения во внешнем виде. Более лучшая изоляция от изменений Какие изменения производятся чаще: логика работы программы или HTML для её отображения? Вообще-то, ответ не важен, каким бы он не был. Шаблоны могут быть хорошим уровнем абстракции между логикой программы и логикой отображения, позволяя обновлять одно, не затрагивая другое. Разделение труда Отделение своего Perl-код от HTML подразумевает, что когда ваш отдел маркетинга решит, что все должно быть зеленым, а не голубым, вам не придется и пальцем пошевелить. Просто пошлите их к HTML-верстальщику этажом ниже. Это здорово, отдаляться от проблем HTML. Даже если в вашей организации одни и те же люди пишут и Perl-код, и HTML-код, то, по крайней мере, у вас остается возможность привлечь к параллельной работе над проектом большего количества людей. В чем различия?Прежде чем мы посмотрим на доступные варианты, давайте посмотрим на объяснение некоторых вещей, которые делают их разными. Модели исполнения Хотя некоторые пытаются быть независимыми от этого, большинство шаблонизаторов предполагают использование некоторой вариации из двух основных моделей исполнения, «pipeline» и «callback». В стиле callback, вы можете сделать шаблон, имеющий программный контроль над данными, внесенными в него. Он использует вызовы к модулям или части встроенного Perl-кода для получения данных для отображения или осуществления таких действий, как аутентификация пользователя. Системы, использующие эту модель: Mason, Embperl и Apache::ASP. Стиль pipeline производит всю работу в стандартном CGI или mod_perl обработчике, а затем решает, какой шаблон использовать и передает в него некоторые данные. Внутри у такого шаблона нет контроля над потоком, только логика отображения, например «показывать это изображение, если этот элемент продается». Популярные системы, поддерживающие этот подход: HTML::Template и Template Toolkit. Модель callback хорошо работает на сайтах, ориентированных на публикации, где страницы в высокой мере смешаны и представляют собой набор статей и списков. В идеале, сайт может быть разбит на визуальные компоненты или куски страниц, чего, в общем-то, достаточно для HTML-верстальщика для рекомбинации их в совершенно новые виды страниц без какой-либо помощи программиста. Модель callback может стать немного сложной, когда вам требуется код, результат выполнения которого может давать различное содержание. К примеру, если у вас есть система, которая обрабатывает какие-либо поступающие в неё данные и отправляет пользователя к разным страницам, в зависимости от поступивших данных. В таких ситуациях, просто будет прекратить писать массу инклудов и редиректов, или поместить различия между разными страницами в один файл. С другой стороны, callback-подход позволяет работать с меньшим количеством файлов (если Perl-код находится в HTML-файле), а также проще и более понятен многим разработчикам. Это просто шаг от статических файлов к статическим файлам с несколькими встроенными участками кода в них. Вот почему PHP настолько популярен среди разработчиков-новичков. Модель pipeline больше похожа на традиционную модель дизайна. Работа с ней может дать дополнительные возможности настройки отображения, чем подход, при котором в начале запроса вы не знаете, какие данные нужны. Вы можете производить запросы к базе данных, делать более удачное кеширование и т.д. Она может также давать более чистое разделение логики приложения и отображения. Как бы то ни было, этот подход требует больше времени для изучения, так как является более сложной концепцией и всегда влечет за собой использование, по меньшей мере, двух файлов: в одном Perl-код, в другом шаблон. Учтите, что многие системы дают существенную гибкость для настройки их модели исполнения. Например, пользователи Mason могут написать отдельные компоненты для логики программы и отображения, позволяя компонентам логики выбирать, какой компонент отображения запустить после обработки их данных. Это позволяет использовать их в стиле pipeline. Приложение с Template Toolkit может быть написано с использованием простого основного обработчика (так же, как во включенном в дитрибутив Apache::Template) со всей остальной логикой приложения, помещенной в шаблон, с использованием вызовов объектов или встроенного кода на Perl. Это позволяет использовать его в стиле callback. HTML::Template и некоторые из процессоров AxKit XML явно настаивают на подходе pipeline. Они не предоставляют методов для обратного вызова Perl-кода во время стадии форматирования HTML, и вам приходится производить эту работу до запуска шаблона. Авторы этих модулей считают это возможностью, которая позволяет предупреждать разработчиков от мошенничества при разделении кода приложения и отображения. ЯзыкиВот в чем большая проблема шаблонизаторов. То, что всегда вызывает флейм в списках рассылки веб-разработчиков. Некоторые системы используют встроенные выражения на Perl. Они могут предоставлять некоторую расширенную семантику, как операторы Embperl для указания мест для вывода результатов работы кода на Perl или секции <%init> для указания времени выполнения кода, но в конце концов, ваши шаблоны будут написаны на Perl. Другие системы дают специальные мини-языки вместо (или вдобавок) втроенному Perl. Обычно этого синтаксиса достаточно для обработки переменных подстановок, условий и циклов. HTML::Template и Template Toolkit — популярные системы, использующие такой подход. AxKit преодолевает препятствие, предоставляя и (не-такой-уж-и-) мини-язык — XSLT, — и подход встроенного Perl — XPathScript. Вот как может происходит дискуссия между достоинствами каждого из этих подходов: Встроенный: Мини-языки тупы. Я уже знаю Perl, и этого просто достаточно. Почему вы хотите использовать что-то другое? Мини-язык: Потому что мой HTML-кодер не знает Perl, а так ему легче. Встроенный: Может, ему стоит немного изучить Perl. Ему будут больше платить. Мини-язык: Как бы то ни было. Вы просто хотите использовать встроенный Perl, поэтому вы можете обрабатывать измененные запросы, помещая небольшие хаки в шаблон, вместо того, чтобы вносить изменения в ваши модули. Это неряшливое кодирование. Встроенный: Это эффективное кодирование. Я могу набросать скрипты редактирования данных вдвое быстрее вас, а потом могу вернуться назад, поместив весь встроенный код в модули и просто заставить шаблоны вызывать его. Мини-язык: Можете, но не будете. Встроенный: И не холодно там, в башне из слоновой кости? Мини-язык: Иди пиши на VBScript, сосунок. и так далее. Большинство людей выбирают сторону в этой войне и остаются там. Если вы один из тех немногих, кто ещё не решил, вы должны потратить немного подумать о тех, кто будет писать и работать с вашими шаблонами, какие навыки у этих людей есть и что позволит им работать наиболее эффективно. Вот пример простого шаблона, написанного сначала в стиле встроенного кода (в данном случае Apache::ASP), а затем — в стиле мини-языка (Template Toolkit). Этот код выбирает объект и показывает некоторые его свойства. В обоих примерах использована идентичная структура данных. Сначала Apache::ASP: <% my $product = Product->load('sku' => 'bar1234'); %> <% if ($product->isbn) { %> Это книга! <% } else { %> Это НЕ книга! <% } %> <% foreach my $item (@{$product->related}) { %> Также вам понравится <% $item->name %>. <% } %> А теперь Template Toolkit: [% USE product(sku=bar1234) %] [% IF product.isbn %] Это книга! [% ELSE %] Это НЕ книга! [% END %] [% FOREACH item = product.related %] Также вам понравится [% item.name %]. [% END %] Есть и третий подход, основанный на парсинге HTML-документа и построения дерева DOM, с последующим манипулированием содержимого узлов. Единственный модуль, который использует такой подход — HTML_Tree. Идея близка к использованию мини-языка, но не требует каких-либо нестандартных HTML-тегов и какой-либо логики для циклов или условий в самом шаблоне. Это хорошо, так как ваши шаблоны будут валидными HTML-документами, которые можно просмотреть в браузере и с которыми можно работать в большинстве стандартных HTML-утилит. Также люди, работающие с этими шаблонами, могут поместить в них временные данные для тестирования и просто заменить их при использовании шаблона. Эта возможность просмотра не работает только тогда, когда вам нужны в шаблоне конструкции if/else. В такой ситуации, и if и else участки HTML будут показаны при просмотре. Парсеры и кешированиеПарсеры для этих шаблонизаторов реализованы по одному из трех способов: они парсят шаблон каждый раз («повторный парсинг»), парсят и кешируют результирующие дерево парсинга («кешированное дерево парсинга») или парсят их, конвертируют в Perl-код и компилируют («скомпилированный»). Системы, компилирующие шаблоны в Perl-код имеют преимущество за счет времени выполнения Perl-кода, дающего мощную производительность вычислений. Они обрабатывают шаблон, генерируют часть кода на Perl и вызывают eval для сгенерированного кода. После этого, следующие запросы к шаблону могут быть обработаны запуском скомпилированного байт-кода в памяти. Сложность шагов парсинга и генерации кода зависит от числа ненужных свойств, предоставляемых системой после следующих встроенных выражений на Perl. Компилирование в Perl, а затем и в Perl байт-код медленное при первом запуске, но дает превосходную производительность, после того, как шаблон уже скомпилирован, так как шаблон становится вызовом Perl-подпрограммы. Аналогичный подход используется в системах, вроде JSP (Java ServerPages). Он наиболее эффективен в средах с внедряющими интерпретаторами Perl, как, например, mod_perl. HTML::Template, HTML_Tree, и бета-версия Embperl 2.0 используют подход кешированного дерева парсинга. Они парсят шаблоны в их особенные внутренние структуры данных, а затем хранят пропарсенную структуру для каждого обработанного шаблона в памяти. Этот подход похож на компилированный Perl в плане производительности и затрат памяти, но не требует генерации кода на Perl и поэтому в нем нет шага eval. Что быстрее: кешировать дерево парсинга или компилирование? Трудно их сравнивать объективно, но факты свидетельствуют о превосходстве компиляции. В версии 1 в Template Toolkit использовался подход кешированного дерева парсинга, но в версии 2 был осуществлен переход к компиляции, после того, как тесты показали, что такой подход дает значительное увеличение скорости. Как бы то ни было, как будет сказано позже, каждый подход более чем достаточно быстр. В отличие от этого, подход повторяющегося парсинга может казаться медленным. Тем не менее, он может быть достаточно быстр, если маркеры будут парситься достаточно быстро. Системы, использующие этот подход, обычно используют простые маркеры, что позволяет им использовать быстрые и простые парсеры. Зачем вам использовать систему с этим подходам, если компиляция дает лучшую производительность? Что ж, в средах без стабильного интерпретатора Perl, вроде обычного CGI он действительно может работать быстрее, чем подход компиляции, в то время как стоимость установки меньше. Кеширование байт-кода Perl системами компиляции становится бесполезным, когда интерпретатор Perl не обрабатывает более одного запроса. Также существуют и другие причины. Скомпилированный код Perl требует много памяти. Если у вас есть много разных шаблонов, они могут быстро сложиться. Представьте, как много памяти потребуется, если каждой странице, использующей server-side includes (SSI) придется оставаться в памяти после того, как к ней будет произведен доступ (не волнуйтесь, модуль Apache::SSI не использует компиляцию, поэтому не вызовет таких проблем). Фреймворки приложений против обычных шаблоновНекоторые из шаблонизаторов пытаются дать комплексное решение задач веб-разработки. Другие предоставляют только шаблоны и подразумевают, что вы дополните их другими модулями для построение полной системы. Некоторые дополнительные возможности фреймворков включают в себя: Преобразование URL Все фреймворки предоставляют способ преобразовать URL в файл шаблона. В дополнение к простому преобразованиям, похожим на обработку статичных документов, некоторые дают способы перехвата всех запросов в отдельную директорию для предварительной обработки или создания схемы наследования объектов вне структуры директорий сайта. Контроль сессии Большинству интерактивных сайтов требуется какой-либо способ контроля сессии для сопоставления данных приложения с пользователем. Некоторые инструменты делают это просто, обрабатывая все куки или дополняя URL, что позволяет вам просто считывать и записывать данные из объекта или хеша, содержащего текущие пользовательские данные. Общепринятым способом хранения является использование модуля Apache::Session. Кеширование выходящих данных Кеширование — ключ к высокой производительности во многих веб-системах, и некоторые из этих инструментов предоставляет контролируемое пользователем кеширование выходящих данных. Это одна из основных возможностей и Mason, и AxKit. AxKit может кешировать на уровне страницы, в то время как Mason также дает хорошо разветвленное кеширование компонентов на странице. Обработка форм Как вы будете жить без CGI.pm для парсинга поступающих данных из форм? Многие из этих инструментов сделают это за вас, делая их доступными в подходящей структуре данных. Некоторые также проводят валидацию поступающих из формы данных, и даже дают «клеющиеся» виджеты форм, которые хранят выбранные значения при повторном просмотре или установке значений по умолчанию, данных вами. Отладка Всем известно, какой тяжелой может быть отладка CGI-скрипта. Шаблонизаторы могут сделать её ещё хуже, испортив номера строк Perl-кода сгенерированным кодом. Чтобы помочь исправить проблему, которую они создают, некоторые предоставляют поддержку отладки, включая дополнительное логирование или интеграцию с отладчиком Perl. Если вы хотите использовать систему, которая просто работает с шаблонами, но вам нужны некоторые из этих дополнительных возможностей, не думайте, что вам придется реализовывать их самим, так как существует несколько инструментов на CPAN, предоставляющих фреймворк, который вы можете собрать. libservlet, дающая интерфейс, похожий на Java servlet API, независима от любого шаблонизатора. Apache::PageKit и CGI::Application — ещё два варианта решения проблемы, но каждый из них в настоящее время связан с HTML::Template. OpenInteract — другой фреймворк, связанный с Template Toolkit. Каждый из них может быть адаптирован для выбранного вами модуля «обычных шаблонов» с минимальными трудозатратами. КонкурентыХорошо, а теперь, когда вы знаете кое-что о том, что отличает эти инструменты друг от друга, давайте посмотрим на популярные Perl шаблонизаторы. Это неполный список: я включил в него только системы, которые развиваются в настоящее время, хорошо задокументированы и имеют значительное сообщество пользователей. Короче говоря, я не рассматривал около дюжины менее популярный систем. В конце этого раздела статьи, я укажу на несколько систем, которые не так хорошо используются, но на которые стоит обратить внимание. SSI SSI — дедушка шаблонизаторов и первый, который люди использовали с тех пор, как он стал стандартной частью большинства веб-серверов. С установленным mod_perl, mod_include дает дополнительную мощность. В частности, он способен принимать новую директиву #perl, которая позволяет делать встроенные вызовы подпрограмм. Также он может эффективно подключать выходные данные скриптов Apache::Registry, используя модуль Apache::Include. Модуль Apache::SSI реализует функциональность mod_include напрямую в Perl, с помощью подключения дополнительной директивы #perl. Главными причинами использовать его являются последующая обработка выходящих данных другого обработчика (с помощью Apache::Filter) или добавление ваших собственных директив. Легко добавлять директивы через подклассы. Вас может привлечь реализация сложного обработчика шаблонов в этом стиле, с помощью добавления циклов и других конструкций, но, возможно, это не будет проблемой с таким большим количеством инструментов. SSI следует модели callback и в большинстве случаев использует мини-язык, хотя вы можете вставлять код на Perl в качестве анонимных подпрограмм в директивах #perl. Так как SSI использует реализацию повторного парсинга, он будет безопасен для использования с большим количеством файлов без опаски о поглощении памяти. SSI — хороший выбор для сайтов, которым нужна очень простая модель шаблонов, особенно для таких, где необходимо просто сделать общими несколько стандартных заголовков и нижних колонтитулов. Тем не менее, вы должны понадобится, понадобится ли вашему сайту рост в нечто большее с большей гибкостью и мощностью, прежде чем останавливаться на этом простом подходе. HTML::Mason http://www.masonhq.com/ Mason, просуществовав несколько лет, заслужил верных последователей. Изначально он создавался как Perl клон наиболее интересных возможностей из Vignette StoryServer, но впоследствии стал уникальным. Он предназначен для публикаций и включает в себя возможности, ориентированные на разделение страниц в части (или компоненты) для повторного использования. Mason использует встроенный Perl вместе с подходом компиляции, но имеет возможность в помощи ограждения кода на Perl от кода на HTML. Компоненты (шаблоны) могут включать в себя раздел Perl-кода в конце файла, заключенный в специальный тег, информирующий о том, что он должен быть исполнен до остального шаблона. Это позволяет программистам помещать логику компонента вниз, подальше от HTML, а затем использовать короткие фрагменты встроенного в HTML Perl-кода для вставки значений, циклов по спискам и т.д. Mason — это фреймворк для разработки сайта, а не простой шаблонизатор. Он включает в себя удобную возможность кеширования, которая может быть использована для сбора выходящих данных из компонент или просто для хранения данных, вычисление которых требует затрат. В настоящее время, это едиственный инструмент, который предоставляет такой тип кеширования в качестве встроенного. Он также реализует схему парсинга аргументов, которая позволяет компоненту указать имена, типы и значения по умолчанию, которые ожидаются быть полученными, как из другого компонента, так и из значений, полученных из строки запроса URI. В то время, как документация в основном демонстрирует модель исполнения callback, существует возможность использовать Mason в стиле pipeline. Это может быть сделано разными способами, включая создание специальных компонент, называемых «автообработчиками», которые запускаются раньше всех при запросах в отдельное дерево директорий. Автообработчик может осуществлять некоторую обработку и настройку данных для показа шаблона, который включает в себя минимальное количество встроенного Perl-кода. Также есть поддержка объектно-ориентированного подхода к сайтам, включая такую концепцию, как наследование по отношению к структуре директорий сайта. Например, компонент автообработчика на /store/book/ может наследовать стандартную верстку от автообработчки на /store/, но перезаписывать цвет фона и панель навигации. И /store/music/ может делать тоже самое, но с другим цветом. Это может быть мощной парадигмой для разработки больших сайтов. Учтите, что это наследование поддерживается только на уровне методов, определенных в компонентах автообработчика. Вы не можете перезаписать компонент /store/foo.html другим на /store/book/foo.html. Подход в Mason к отладке — использование &laqou;отладочных файлов», которые Mason может запускать вне среды веб-сервера, производя мнимый веб-запрос и активируя отладчик. Это может быть полезно, если у вас проблемы с тем, чтобы заставить Apache::DB работать без перебоев с mod_perl или при использовании среды запуска, которая не предоставляет встроенную поддержку отладчика. Другой уникальной возможностью является способность оставлять большие статичные текстовые части большого шаблона на диске и помещать их в файл при необходимости, вместо того, чтобы держать в оперативной памяти. Эти дает некоторую скорость для значительного сохранения памяти при работе с шаблонами, в основном состоящими из статичного текста. У этого модуля есть также много других возможностей, включая фильтрацию выходящих из HTML данных и утилиту предварительного просмотра страниц. Поддержка сессий не встроена, но включен простой пример, показывающий как интегрировать Apache::Session. Набор возможностей Mason может быть непреодолим для новичков, но высококачественная документация и отзывчивое сообщество пользователей позволяют двигаться в этом направлении. HTML::Embperl http://perl.apache.org/embperl/ Embperl демонстрирует выбор своего языка открыто: встроенный Perl. Это один из наиболее популярных шаблонизаторов во встроенным Perl, который существует дольше остальных. У него твердая репутация за скорость и простоту использования. Чаще всего его используют в стиле callback, с перехватом URI и обработкой запрошенных файлов. Тем не менее, опционально он может быть запущен из подпрограммы другой программы, позволяя использовать себя в стиле pipeline. Шаблоны компилируются в байт-код Perl и кешируются. Embperl существует достаточно долго, что позволило ему создать впечатляющий список возможностей. Он имеет возможность запускать код внутри ячейки Safe, поддержку автоматической отчистки глобальных имен для того, чтобы сделать программирование с mod_perl проще и хорошие инструменты отладки, включающие в себя возможности отправки ошибок по e-mail администратору. Главной вещью, которая ставит Embperl отдельно от других систем со встроенным Perl, является тесная интеграция с HTML. Он может распознать теги TABLE и автоматически пройти по ним по длине массива. Он автоматически предоставляет формы клеящихся виджетов. Ссылка на массив или хеш, помещенная в конце строки запроса в аттрибут HREF или SRC будет автоматически разобрана в строку запроса в формате «имя=значение». Теги META HTTP-EQUIV преобразуются в настоящие HTTP-заголовки. Другой причиной, по которой людям нравится Embperl, является то, что он делает некоторые из частых задач по написанию веб-приложений очень простыми. Например, все данные из форм доступны для чтение в волшебной переменной %fdat. Сессии поддерживаются также просто, чтением и записью в волшебный хеш %udat. Также есть хеш для хранения постоянного состояния приложения. Замена спецсимволов HTML производится автоматически (хотя может быть выключена или включена). Embperl включает в себя кое-что под названием EmbperlObject, который позволяет вам применять объекто-ориентированную концепцию для иерархии вашего сайта способом, похожим на возможности автообработчиков и наследования в Mason, указанные выше. Это удобный способ делать сайты со стилем, который меняется от местонахождения, который достоин изучения. EmbperlObject включает в себя возможность делать подмены на уровне файлов. Это означает, что у вас могут быть директории, вроде /store/music, которые подменяют специальные шаблоны, наследуя все остальное из родительской директории. Единственным недостатком старых версий Embperl была необходимость использовать встроенные замены большинства управляющих структур Perl, вроде if и foreach, когда они были заключены в разделы не на Perl: [$ if ($foo) $] Looks like a foo! [$ else $] Nope, it's a bar. [$ endif $] Это решение может быть неподходящим в системах, основанных на встроенном Perl. Начиная с версии 1.2b2, вместо этого стало возможно использовать стандартный синтаксис: [$ if ($foo) { $] Looks like a foo! [$ } else { $] Nope, it's a bar. [$ } $] К моменту написания статьи, новая ветвь Embperl 2.x находится в стадии бета-тестирования. Они включает в себя некоторые интересные возможности, как более гибкая схема парсинга, которая может быть подстроена под вкусы пользователя. Он также поддерживает прямое использование шаблонов Embperl в отладчике Perl и дает улучшение производительности. Apache::AxKit http://axkit.org/ AxKit — первая mod_perl-система генерирования страниц, построенная на XML. С технической точки зрения, AxKit не является шаблонизатором, а скорее представляет собой фрейморк для объединения вместе нескольких модулей, которые генерируют и передают XML-данные. На самом деле, он может опционально использовать Template Toolkit в качестве языка передачи XML. Как бы то ни было, он заслуживает изучения здесь, так как предоставляет некоторые инструменты для шаблонов, которые больше нигде не представлены. Проще говоря, AxKit преобразовывает файлы XML в таблицы стилей XSL, которые он может обработать используя популярные XSLT модули, вроде XML::XSLT или XML::Sablotron. Правила преобразования таблицы в запрос являются гибкими и они могут объединять строки запроса, куки и другие аттрибуты запроса. Идея в том, что вы можете использовать эту возможность, чтобы обработать широкий круг клиентов с разными возможностями отображения, выбирая нужную таблицу. Понимая, что не каждый является фанатом несколько непонятного синтаксиса XSL, Matt Sergeant предоставил альтернативный язык таблиц стилей под названием XPathScript. XPathScript позволяет вам написание таблицы стилей, используя текст со встроенным кодом Perl. Это похоже на другие шаблонизаторы со встроенным Perl, но нацелено на использование встроенных функций XPath для запросов в XML-документ и манипулирования полученными данными. XPathScript также может быть использован в декларативном стиле, определяя форматирование отдельных элементов поступающих XML данных. Например, этот код будет менять все теги <foo> на BAR на выходе: <% $t->{'foo'}{pre} = 'BAR'; $t->{'foo'}{post} = ''; $t->{'foo'}{showtag} = 0; %> <%= apply_templates() %> Используя функцию include из XPathScript (которая выглядит как в SSI), вы можете построить библиотеки полезных преобразований, использующих эту технику. Хорошо, если у вас есть набор XML-файлов, находящихся где-то на диске, но как насчет динамического контента? AxKit обрабатывает его, позволяя вам заменять различные источники данных на один, основанный на файлах. Он может включать запуск некоторого динамического кода в ответ на каждый запрос для генерации XML-данных, которые будут преобразованы. Для этого дистрибутив включает в себя модуль под названием XSP. XSP — язык для построения XML DOM с использованием встроенного Perl библиотек тегов. Библиотеки тегов определены как таблицы стилей, которые могут преобразовывать теги XML в Perl-код. Это демонстрируется через включенную библиотеку тегов SQL, которая позволяет вам записывать страницу XSP, используя теги XML, которые будут подключать к базе данных, выполнять запросы и генерировать XML-документ с результатами. У AxKit есть несколько хороших встроенных инструментов для повышения производительности. Он может кешировать все выходные данные и обрабатывать их как статический файл при последующем запросе. Он также может сжимать выходные данные для ускорения загрузок тем браузерам, которые понимают кодировку gzip. Это может быть сделано и в других системах, но потребует от вас установку дополнительного программного обеспечения. Используя AxKit, достаточно будет просто включить их файле настроек. Если все эти языки, библиотеки тегов и таблиц стилей звучат ужасно для вас, AxKit может быть разрушающим для вашего проекта. Тем не менее, AxKit имеет превосходство, будучи построен на утвержденных стандартах W3C и многие из навыков в разработке с его помощью могут быть применены к другим языкам и инструментам. Apache::ASP http://www.apache-asp.org/ Apache::ASP был начат как порт технологии Active Server Pages от Microsoft, и его основной дизайн следует этой модели. Он использует встроенный Perl вместе с подходом компиляции и предоставляет набор простых объектов для доступа к информации о запросе и формулировании ответа. Скрипты, написанные для ASP от Microsoft с использованием Perl (с помощью ActiveState PerlScript) обычно могут быть запущены на этой системе без изменений (страницы, написанные на VBScript не поддерживаются). Как и обычный ASP, у него есть перехватчики для вызова специального кода при возникновении определенных событий, как, например, старт новой сессии пользователя. Он также предоставляет такое же простое управление состоянием и сессиями. Хранение и извлечение данных о состоянии всего приложения или отдельного пользователя так же просты, как и одиночный вызов метода. Он может даже поддерживать пользовательские сессии без куки, — уникальная возможность среди этих систем. Дополнительной значительной возможностью, которая не пришла от Microsoft ASP — это поддержка XML и XSLT. Предоставлены две опции: XMLSubs и преобразования XSLT. XMLSubs — способ добавить обычные теги в ваши страницы. Он заменяет XML-теги вашими подпрограммами, так что вы можете добавить что-то вроде ?<site:header page="Page Title" /> в ваши страницы и переводить это вызовом подрограммы, вроде &site::header({title => "Page Title"}). Он может хорошо обрабатывать XML-теги с текстом в теле. Поддержка XSLT позволяет фильтровать выходные данных ASP-скриптов через XSLT для отображения. Это позволяет вашим ASP-скриптам генерировать XML-данные, а затем форматировать эти данные с помощью отдельной таблицы стилей XSL. Это поддержка предоставляется через интеграцию с модулем XML::XSLT. Apache::ASP предоставляет клеящиеся виджеты для форм с помощью использования модуля HTML::FillInForm. Он также имеет встроенную поддержку удаления лишних пробелов в выходящих данных, сжатие выходящих данных Одну вещь надо учесть об управлении сессии и состояния в этой системе — в настоящее время он поддерживает только кластеры, используя сетевые файловые системы, как NFS или SMB (Joshua Chamas, автор модуля, сообщает о гораздо более лучших результатах работы на Samba, чем на NFS). Это может быть проблемой на больших кластерах, которые обычно зависят от реляционной базы данных для сетевого хранения сессий. Поддержка для хранения данных о сессии в базе данных планируется в будущих релизах. А тем временем, имеются инструкции о подключении Apache::Session. Text::Template http://search.cpan.org/search?dist=Text-Template Этот модуль на CPAN стал стандартом де-факто для основных задач использования шаблонов. У него простой интерфейс и документация. Примеры в документации демонстрируют стиль исполнения pipeline, но написать обработчик mod_perl, который будет напрямую вызывать шаблоны, подобно стилю callback, довольно просто. Модуль использует встроенный Perl. У него есть возможность запускать встроенный Perl в ячейке Safe, в случае, если вы беспокоитесь, что ошибки в коде могут вывести из строя сервер. Модуль основан на творческом использовании встроенного кода для предоставления вещей, которые люди обычно ожидают от шаблонизаторов, вроде инклудов. Это может быть и хорошо, и плохо. Например, для подключения файла вы можете просто вызвать Text::Template::fill_in_file(имяфайла). Как бы то ни было, вам придется указать полный путь к файлу и ничто не остановит вас от использования /etc/passwd в качестве файла для инклуда. Большинство модных шаблонизаторов имеют концепции, вроде путей к инклудам, которые позволяют вам указывать список директорий, в которых следует искать подключаемые файлы. Вы можете написать подпрограмму, работающую в этом направлении и сделать её доступной в пространстве имен вашего шаблона, но не встроенную внутрь него. Каждый шаблон загружается в качестве отдельного объекта. Шаблоны компилируются в Perl, и парсинг проводится только при первом использовании. Тем не менее, для получения полной отдачи от этого кеширования в постоянном окружении, вроде mod_perl, вашей программе придется вести контроль, над тем, какой шаблон был использован, так как у Text::Template нет глобального контроля этого, и возвращать кешированные шаблоны, когда это возможно. Text::Template не привязан к HTML, а просто модуль шаблонизатора, не являющийся фреймворком веб-приложения. Он идеален для генерирования e-mail, PDF и т.д. Template Toolkit http://template-toolkit.org/ Один из недавних пополнений на сцене шаблонизаторов, Template Toolkit является гибкой системой, использующей мини-язык. Он имеет полный набор директив для работы с данными, включая цикла и условия, а также он может быть расширен несколькими путями. Встроенный Perl-код может быть включен с помощью изменений настроек, но обычно этого не делают. Он использует компиляцию, кеширование скомпилированного байт-кода в памяти и опциональное кеширование сгенерированного Perl-кода для шаблонов на диск. Хотя он чаще используется в стиле pipeline, подключенный модуль Apache::Template позволяет обращаться к шаблонам непосредственно из URL. Template Toolkit обладает большим набором возможностей, поэтому здесь мы сможем изучить только самые яркие из них. В дистрибутив TT включен большой набор основательной и качественной документации, так что будет просто изучить далее то, что вы выберите. Одна из главных возможностей, отличающих TT от других систем — предоставление простого доступа к сложным структурам данных через концепцию оператора точки. Это позволяет людям, не знающим Perl, получать доступ к вложенным спискам и хешам или вызывать методы объектов. Например, мы можем обратиться к следующей структуре данных на Perl: $vars = { customer => { name => 'Bubbles', address => { city => 'Townsville', } } }; Затем мы можем ссылкаться к вложенным данным в шаблоне: Hi there, [% customer.name %]! How are things in [% customer.address.city %]? Это проще и более универсалный, чем эквивалентный синтаксис в Perl. Если мы обращаемся к объекту, как к части структуры данных, мы можем использовать аналогичную форму записи для вызова методов внутри объекта. Если вы смоделировали данные вашей системы как набор объектов, это может подойти. Шаблоны могут определять макросы и включать другие шаблоны, а параметры могут быть переданы в каждый. Подключенные шаблоны могут опционально локализировать их переменные, так что изменения, произведенные во время выполнения подключенного шаблона, не повлияют на значения переменных в большей области видимости. Существует директива фильтрации, которая может быть использована для последующей обработки выходящих данных. Это может использоваться от простого преобразования HTML до автоматического досрочного завершения обработки вычислений (полезно для выпадающих меню, когда вы хотите ограничить размер записей) и вывода в STDERR. TT поддерживает API для плагинов, который может быть использован для добавления дополнительных возможностей вашим шаблонам. Предоставляемые данные могут широко использоваться для доступа к данным и форматирования. Стандартные плагины доступа к данным включают в себя модули для доступа к источникам данных XML или DBI и использования этих данных в вашем шаблоне. Существует также плагин для доступа к CGI.pm. Плагины для форматирования позволяют отображать вещи, вроде дат и цен в локализированном виде. Также существует плагин для таблиц, который используется для отображения списков в виде нескольких колонок. Такие плагины форматирования выполняют хорошую работу по решению последних 5 процентов проблем по отображению данных, которые часто затрагивают людей, которые используют доморощенные системы для встраивания небольших участков HTML в свои Perl-модули. Похожим образом, TT включает в себя несколько удобных возможностей для тех, кто пишет шаблоны, включая удаление пробелов вокруг тегов и возможность изменить ограничители тегов, — вещи, которые могут звучать несколько экзотично, но иногда могут сделать шаблоны значительно более простыми в использовании. Дистрибутив TT также включает в себя скрипт под названием ttree, который позволяет обрабатывать всего дерева директорий с шаблонами. Это полезно для сайтов, которые предварительно публикуют страницы их шаблонов и обрабатывают их статически. Скрипт проверяет время модификации и только страницам, требующим обновления, предоставляется эта функциональность. Дистрибутив также включает примерный набор HTML-виджетов управления шаблонами, который может быть использован, чтобы дополнить коллекцию документации. HTML::Template http://search.cpan.org/search?dist=HTML-Template HTML::Template — популярный модуль среди тех, кто хочет использовать мини-язык, вместо встроенного Perl. Он использует простой набор тегов, которые позволяют делать циклы (даже для вложенных структур данных) и условия в дополнение к основным вставкам значений. Тегам намеренно придан стиль HTML-тегов, что может быть полезно в некоторых ситуациях. Как говорится в документации, «он делает только одну вещь, и делает её быстро и аккуратно», — не производит попыток добавить возможности приложений, как обработка форм или контроль сессии. Модуль следует модели исполнения pipeline. Распарсенные шаблоны хранятся в структуре данных Perl, которая может быть кеширована в любой последовательности памяти, общедоступной памяти (используя IPC::SharedCache) и на диске. Документация полная и хорошо написана, с множеством примеров. Вам может быть интересно, чем этот модуль отличается от Template Toolkit, другого популярного шаблонизатора с мини-языком. Помимо указанных различий в синтаксисе, HTML::Template более быстрый и простой, в то время как Template Toolkit имеет больше возможностей, как плагины и нотация точки. Вот простой пример, сравнивающий синтаксис: HTML::Template: <TMPL_LOOP list> <a href="<TMPL_VAR url>"><b><TMPL_VAR name></b></A> </TMPL_LOOP> Template Toolkit: [% FOREACH list %] <a href="[% url %]"><b>[% name %]</a></a> [% END %] А теперь, несколько великодушных упоминаний: HTML_Tree http://homepage.mac.com/pauljlucas/software/html_tree/ Как было указано ранее, HTML Tree использует уникальный метод создания шаблона: он загружает HTML-страницу, парсит её в DOM, а потом программно модифицирует содержимое узлов. Это позволяет использовать крайне валидные HTML-документы в качестве шаблонов, — это то, чего другие модули не позволяют делать. Кривая изучения может быть немного круче, чем средняя, но это может быть полезно, если вы беспокоитесь о том, чтобы упростить задачу. Учтите, что имя «HTML_Tree» — это не «HTML::Tree» Apache::XPP http://opensource.cnation.com/projects/XPP/ XPP — шаблонизатор со встроенным Perl, который компилируется в байт-код. Не смотря на великолепную реализацию, он мало чем отличается от других, кроме простого механизма определения новых тегов, похожих на теги HTML, которые могут быть использованы для замены встроенного кода в шаблонах. ePerl http://search.cpan.org/search?dist=Apache-ePerl Возможно, первый модуль для встраивания Perl-кода в текстовые или HTML-файлы, ePerl до сих пор жизнеспособен в форме Apache::ePerl. Он кеширует скомпилированный байт-код в памяти для достижения хорошей производительности, и некоторые люди находят его удивительно простым в использовании. CGI::FastTemplate http://search.cpan.org/search?dist=CGI-FastTemplate Этот модуль использует минималистический подход к использованию модулей, что делает его необычно подходящим для использования в CGI-приложениях. Он парсит шаблоны с помощью одного регулярного выражения и не поддерживает ничего другого в шаблонах, кроме простой подстановки переменных. Циклы обрабатываются с помощью подключения выходных данных их других шаблонов. К сожалению, это ведет к стилю программирования на Perl, который более сбивает с толку и к увеличению количества файлов шаблонов. Как бы то ни было, некоторые люди используют этот грязный, но простой подход. ПроизводительностьЛюди всегда беспокоятся о производительности шаблонизаторов. Если вы когда-нибудь разрабатывали крупномасштабное приложение, вам должны быть известны относительные затраты на выполнение различных операций, чтобы знать, что шаблонизатор — не первое место, которое стоит изучать в целях повышения производительности. Все системы, указанные здесь, имеют восхитительные показатели по производительности в постоянных окружениях исполнения, вроде mod_perl. По сравнению с такими ужасно медленными операциями, как выборка данных из базы данных или файла, время, добавленное шаблонизатором, практически незначительно. Есле же вы думаете, что ваш шаблонизатор замедляет работу, проверьте это: подключите Devel::DProf и посмотрите. Если один из указанных в этой статье инструментов будет работать быстрее всего остального, вы должны похлопать себя по спине, — вы произвели отличную работу по настройке вашей системы и удалению критических мест! Что касается меня, я только однажды видел такое, когда я успешно смог закешировать почти каждую часть задачи по обработке запроса, кроме запуска шаблона. Как бы то ни было, для ситуации, когда вам надо выжать немного дополнительных микросекунд из времени генерации вашей страницы, существуют различия в производительности между системами. Они примерно такие, как вы и ожидали: системы, делающие меньше всего, работают быстрее всего. Использование встроенных выражений print() быстрее, чем использование шаблонов. Использование простых подстановок быстрее, чем использование встроенного кода Perl. Использование встроенного кода Perl быстрее, чем использование мини-языка. Единственный сравнительный тест, существующий на время написания этой статьи, сделал Joshua Chamas: тест «hello world», который просто проверяет, как быстро каждая система может выплюнуть эти знаменитые слова и тест «hello 2000», который проверяет основные функции, используемые в большинстве динамических страниц. Он доступен по следующему адресу: http://www.chamas.com/bench/index.html Беспокойства о производительности CGI Если вы работаете с CGI, лучше побеспокойтесь о том, какую рыбу пожарить на ужин, чем о производительности вашего шаблонизатора. И все-таки, некоторые люди прилипли к CGI, но все равно хотят использовать шаблонизатор с приемлемой производительностью. CGI коварен, и вам приходится переживать о том, сколько раз он запросит Perl скомпилировать код для большого шаблонизатора при каждом запросе. CGI также разрушает кеширование шаблонов в памяти, которое используется в большинстве этих систем, хотя медленное кеширование на диск, которое предоставляют Mason, HTML::Template и Template Toolkit, будет работать. Наибольшей производительности с CGI вы добьетесь при использовании простых инструментов, вроде CGI::FastTemplate или Text::Template. Они небольшие и быстро компилируются, а CGI::FastTemplate дает дополнительное повышение производительности, производя простой парсинг на основе регулярных выражений и не выполняет никакого встроенного Perl-кода. Почти все, что указано в этой статье, будет добавлять десятые доли секунд к времени компиляции каждой страницы. |