Плагин для Smarty — Combine

Плагин позволяет собрать несколько CSS или Javascript файлов воедино.

Я согласен, что подобных программных решений очень много, например Minify, YUI Compressor или конкантенатор из Pagespeed service от Google. Но для шаблонизатора Smarty мне подобного не попадалось, и я решил написать свое и попроще.
Combine
Плагин работает довольно просто: когда один из включаемых файлов изменяется, он создает новый выходной файл и возвращает к нему путь.

Плагин позволяет решить 2 проблемы — модульность и контроль за обновлением файлов на стороне клиента.
Проблема модульности заключается в том, что для относительно сложных проектов приходится подключать большое число разных CSS и JS файлов. Все это приводит к дополнительным запросам к серверу. Да, front-end сервера с этим прекрасно справляются, но зачем делать 10 запросов, когда можно сделать один? А если хочется сократить это число привычными методами, приходится использовать различные дополнительные решения или собирать файл вручную. Лично для меня, файл после первой 1000 строк превращается в адское месиво, поэтому я стараюсь разделять код на несколько модулей или фрагментов.
Проблема контроля за обновлением ресурсов на стороне клиента не менее важна. Наверняка многие сталкивались со старой версией CSS или JS файла у какого-нибудь клиента, которая вызывала ошибку из-за изменившейся верстки или API на back-end'e. И тут подводных камней действительно много, т.к. кэширование зависит и от браузера, и от прокси, а может еще и от провайдера зависеть (редко, но некоторые держат прозрачный прокси). Единственный стопроцентно рабочий способ — изменить имя файла. Остальные могут не сработать.

У плагина есть список из трех входных параметров:
  1. input, представляющий собой простой массив, содержащий в себе список путей к склеиваемым файлам;
  2. output, представляющий собой путь к выходному файлу;
  3. age, время в секундах между проверками на изменение одного из включаемых файлов. Этот параметр можно опустить, по умолчанию он равен 3600 секундам.

Расскажу зачем нужен age — операции ввода-вывода одни из самых проблемных на сегодняшний день. Несмотря на появление SSD-накопителей, время доступа к файлу все же присутствует и, если много обращений к файлам, в приложении могут возникать проблемы производительности. Сейчас это все хорошо кэшируется, но зачем же обращаться в кэш, когда этого можно не делать? Каждый разработчик сам вправе регулировать частоту проверки на актуальность файлов, но я бы не рекомендовал ставить меньше 3 секунд, так как это почти бессмысленно. В своих проектах я передаю этот параметр в виде переменной, которая зависит от режима работы сайта. Если сайт находится в режиме отладки, там 5 секунд, в противном случае — 3600.

Исходный код

Код доступен на GitHub.

Образец подключения в шаблоне

В Smarty 3 есть возможность создания массива на лету, поэтому код приведен с учетом этой возможности. Для Smarty 2 массив нужно передавать через отдельную переменную.

<script type="text/javascript"
src="/{combine input=array('/js/core.js','/js/slideviewer.js') output='/js/big.js' age='30'}" >



При работе плагина есть несколько ньюансов. Путь к файлам должен идти от document_root, а папка с выходным файлом должна разрешать запись и создание новых файлов. Нельзя одновременно объединять файлы CSS и JS.

Плагин протестирован с Smarty 2 и Smarty 3. Сейчас используется в проекте с посещаемостью около 4000 человек в сутки. Проблем не наблюдал. Буду благодарен за багрепорты и предложения по развитию.
Метки:
Поделиться публикацией
Похожие публикации
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 10
  • 0
    Генерация происходит в момент компиляции Smarty-шаблона или сначала генерируется специальна ссылка, которая ведет к скрипту, который при первом обращении сгенерирует соответствующий упакованный JS файл?

    + Забыли про CDN и уже закешированные в браузере пользователя библиотеки.
    • 0
      Генерация ссылки происходит в момент компиляции шаблона.
    • +4
      Очередной велосипед?

      function sfc_get_file_ext($filename) {
          $rm=explode(".", $filename);
          if(is_array($rm)) {
              if (isset($rm[count($rm)-1]))	{
                  return $rm[count($rm)-1];
             }
          }
         return '';
      }
      


      Так по моему проще:

      function sfc_get_file_ext($filename) {
          return pathinfo($filename, PATHINFO_EXTENSION);
      }
      
      • 0
        Вы безусловно правы. Обновлю код обязательно.
        • 0
          Можно и через (но вернет расширение с точкой):
          strrchr($filename, '.')

      • 0
        И зачем постоянно проверять на function_exists?

        if (!function_exists('sfc_get_file_ext')) {
        		function sfc_get_file_ext($filename) {
        


        Не легче ли было объявить эти фукнции наравне с самой функцией плагина smarty_function_combine?
        • 0
          Может быть привычка Wordpress-разработчика? :)

          С праздником.
        • +1
          Думаю, что в качестве развития, было бы неплохо добавить мимими минимизатор результатов комбинирования — тот же Minify.
          • 0
            А также параметр development, который бы комбинировал скрипты / цсс только на продакшене, подставляя оригиналы при отладке.
            • 0
              Отличная идея, о которой я всерьез задумывался. Полагаю, что со временем введу подобный функционал.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.