Minify для HostCMS - объединение и сжатие скриптов и стилей

#
Minify для HostCMS - объединение и сжатие скриптов и стилей
Осенью на формуе поднимался вопрос об особенностях устройства модуля "Компрессия", входящего в коммерческие редакции HostCMS. Этот модуль, как известно, сжимает только генерируемый системой html, и никак не обрабатывает файлы стилей и скриптов.

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

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

Реализация основана на известной библиотеке Minify - http://code.google.com/p/minify/

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

Итак, для начала скачиваем архив с минимизатором и распаковываем его в корневую папку HostCMS.

Потом открываем файл main_classes.php и дописываем в его конец такую строчку:
require_once (CMS_FOLDER . "min/hostcms_svc.php");


Теперь нам необходим нужных местах макета заменить старый код подключения стилей и скриптов на определение массива стилей и скриптов и вызов функции getLink(). Рассмотрим это на примере стандартного макета "Корпорация".

Вот начало исходного кода макета с id = 1:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
   <title><?php $kernel->show_title() ?></title>
   <meta name="description" content="<?php $kernel->show_description()?>"/>
   <meta name="keywords" content="<?php $kernel->show_keywords()?>" />
   <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
   <meta content="text/html; charset=<?php echo SITE_CODING ?>" http-equiv="Content-Type" />
   <link rel="icon" href="/favicon.ico" type="image/x-icon" />
   <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
    
   <?php $kernel->show_CSS() ?>    
       <link rel="stylesheet" type="text/css" href="/hostcmsfiles/style.css" />

    
   <script type="text/javascript" src="/hostcmsfiles/jquery/jquery.js"></script>   
   <script type="text/javascript" src="/templates/template1/hostcms.js"></script>
   <script type="text/javascript" src="/hostcmsfiles/ajax/JsHttpRequest.js"></script>
   <script type="text/javascript" src="/hostcmsfiles/ajax/ajax.js"></script>
   <script type="text/javascript" src="/hostcmsfiles/main.js"></script>

   
   
   
   <link rel="alternate" type="application/rss+xml" title="HostCMS RSS Feed" href="/news/rss/" />
   
   <!-- Предварительная загрузка изображений -->
   <script type="text/javascript">
   var image1 = new Image(); image1.src = "/hostcmsfiles/images/shadow-b.png";
   var image2 = new Image(); image2.src = "/hostcmsfiles/images/shadow-l.png";
   var image3 = new Image(); image3.src = "/hostcmsfiles/images/shadow-lb.png";
   var image4 = new Image(); image4.src = "/hostcmsfiles/images/shadow-lt.png";
   var image5 = new Image(); image5.src = "/hostcmsfiles/images/shadow-r.png";
   var image6 = new Image(); image6.src = "/hostcmsfiles/images/shadow-rb.png";
   var image7 = new Image(); image7.src = "/hostcmsfiles/images/shadow-rt.png";
   var image8 = new Image(); image8.src = "/hostcmsfiles/images/shadow-t.png";
   var image9 = new Image(); image9.src = "/hostcmsfiles/images/ajax_loader.gif";

   /* Изображения для верхнего меню */
   var image10 = new Image(); image10.src = "/images/red_grad.gif";
   var image11 = new Image(); image11.src = "/images/top_menu_l.gif";
   var image12 = new Image(); image12.src = "/images/top_menu_r.gif";
   </script>
</head>

<body>


Вместо вызова метода show_CSS() и тега link для подключения файла /hostcmsfiles/style.css напишем следующее:
    <?
        // подключим стили
        $styles = array(getCSS_path_for_current_template(), 'hostcmsfiles/style.css');
        echo getLink($styles, 'css');    
    ?>


А вместо тегов script, подключающих внешние файлы, напишем такой код:
    <?
      // подключим скрипты
       $scripts = array('hostcmsfiles/jquery/jquery.js',   
                       'templates/template1/hostcms.js',
                       'hostcmsfiles/ajax/JsHttpRequest.js',
                       'hostcmsfiles/ajax/ajax.js',
                       'hostcmsfiles/main.js');
        echo getLink($scripts, 'js');
   ?>

В итоге получим вот такое начало макета:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
   <title><?php $kernel->show_title() ?></title>
   <meta name="description" content="<?php $kernel->show_description()?>"/>
   <meta name="keywords" content="<?php $kernel->show_keywords()?>" />
   <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
   <meta content="text/html; charset=<?php echo SITE_CODING ?>" http-equiv="Content-Type" />
   <link rel="icon" href="/favicon.ico" type="image/x-icon" />
   <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
    
    <?
        // подключим стили
        $styles = array(getCSS_path_for_current_template(), 'hostcmsfiles/style.css');
        echo getLink($styles, 'css');    
    ?>
    <?
      // подключим скрипты
       $scripts = array('hostcmsfiles/jquery/jquery.js',   
                       'templates/template1/hostcms.js',
                       'hostcmsfiles/ajax/JsHttpRequest.js',
                       'hostcmsfiles/ajax/ajax.js',
                       'hostcmsfiles/main.js');
        echo getLink($scripts, 'js');
   ?>
   
   <link rel="alternate" type="application/rss+xml" title="HostCMS RSS Feed" href="/news/rss/" />
   
   <!-- Предварительная загрузка изображений -->
   <script type="text/javascript">
   var image1 = new Image(); image1.src = "/hostcmsfiles/images/shadow-b.png";
   var image2 = new Image(); image2.src = "/hostcmsfiles/images/shadow-l.png";
   var image3 = new Image(); image3.src = "/hostcmsfiles/images/shadow-lb.png";
   var image4 = new Image(); image4.src = "/hostcmsfiles/images/shadow-lt.png";
   var image5 = new Image(); image5.src = "/hostcmsfiles/images/shadow-r.png";
   var image6 = new Image(); image6.src = "/hostcmsfiles/images/shadow-rb.png";
   var image7 = new Image(); image7.src = "/hostcmsfiles/images/shadow-rt.png";
   var image8 = new Image(); image8.src = "/hostcmsfiles/images/shadow-t.png";
   var image9 = new Image(); image9.src = "/hostcmsfiles/images/ajax_loader.gif";

   /* Изображения для верхнего меню */
   var image10 = new Image(); image10.src = "/images/red_grad.gif";
   var image11 = new Image(); image11.src = "/images/top_menu_l.gif";
   var image12 = new Image(); image12.src = "/images/top_menu_r.gif";
   </script>
</head>

<body>



Теперь, если мы обновим страницу в браузере, и посмотрим ее html-код, то в заголовке документа увидим следующее:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
   <title>Демонстрационный сайт системы управления сайтом HostCMS</title>
   <meta name="description" content="Демонстрационный сайт системы управления сайтом HostCMS"/>
   <meta name="keywords" content="Демонстрационный сайт системы управления сайтом HostCMS" />
   <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
   <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
   <link rel="icon" href="/favicon.ico" type="image/x-icon" />
   <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />

    
    <link rel="stylesheet" media="all" type="text/css" href="/min/f=templates/template1/style.css,hostcmsfiles/style.css&amp;2832961301159641" />
    <script type="text/javascript" src="/min/f=hostcmsfiles/jquery/jquery.js,templates/template1/hostcms.js,hostcmsfiles/ajax/JsHttpRequest.js,hostcmsfiles/ajax/ajax.js,hostcmsfiles/main.js&amp;52718251294478268"></script>
   

   <link rel="alternate" type="application/rss+xml" title="HostCMS RSS Feed" href="/news/rss/" />
   
   <!-- Предварительная загрузка изображений -->
   <script type="text/javascript">
   var image1 = new Image(); image1.src = "/hostcmsfiles/images/shadow-b.png";
   var image2 = new Image(); image2.src = "/hostcmsfiles/images/shadow-l.png";
   var image3 = new Image(); image3.src = "/hostcmsfiles/images/shadow-lb.png";
   var image4 = new Image(); image4.src = "/hostcmsfiles/images/shadow-lt.png";
   var image5 = new Image(); image5.src = "/hostcmsfiles/images/shadow-r.png";
   var image6 = new Image(); image6.src = "/hostcmsfiles/images/shadow-rb.png";
   var image7 = new Image(); image7.src = "/hostcmsfiles/images/shadow-rt.png";
   var image8 = new Image(); image8.src = "/hostcmsfiles/images/shadow-t.png";
   var image9 = new Image(); image9.src = "/hostcmsfiles/images/ajax_loader.gif";

   /* Изображения для верхнего меню */
   var image10 = new Image(); image10.src = "/images/red_grad.gif";
   var image11 = new Image(); image11.src = "/images/top_menu_l.gif";
   var image12 = new Image(); image12.src = "/images/top_menu_r.gif";
   </script>
</head>

<body>

Скрипт объединил все файлы стилей в один файл, сжал его и присвоил ему заголовок expires на год вперед, чтобы наши стили надолго закешировались в браузере у посетителя.
То же самое произошло и со скриптами.

Надо отметить, что при любых изменениях в любом файле стилей или скриптов, при изменении их набора (добавлении или удалении файлов) а также при изменении порядка файлов изменится число, которым завершается url в теге script или href в теге link, что в свою очередь вызовет пересборку объедииненных файлов и их новое сжатие, так что при редактировании скриптов и стилей можно не бояться что пользователь будет использовать устаревшую версию из кеша.

Важные нюансы:

  • В массив могут включаться только те файлы скриптов и стилей, которые находятся на том же домене что и сайт.
  • Обратите внимание, что в массив записываются только относительные пути к файлам, _без_начального_слеша!_
  • Имена файлов скриптов и стилей должны быть записаны только латиницей, в именах файлов не может быть симовола "," (запятая).
  • Первым элементом массива стилей должен быть вызов функции getCSS_path_for_current_template() - она добавляет в массив css-файл от текущего макета.
  • Второй параметр функции getLink() может принимать следующие значения: js, css, css_print и css_screen. При указании значения 'css' в теге link выводится параметр media со значение all.


Отладка.
Объединение файлов в один, в ряде случаев затрудняет отладку. Здесь можно пойти двумя путями.
1. У функции getLink() есть еще третий параметр. Если в качестве третьего параметра указать true, то объединения и компрессии файлов происходить не будет, и функция getLink() вернет набор из нескольких тегов link или script, по одному для каждого файла в переданном массиве.
2. Можно перейти в раздел Константы центра администрирования, и создать там константу с названием MINIFY_IN_DEBUG_MODE, присвоив ей значение true. Активация этой константы будет переводить функцию getLink() в режим отладки на всех сайтах системы.

Загружаем и пользуемся!
Заказов не беру. Консультирую редко.
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Библиотека недоступна.
http://www.aiventa.ru
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
hell0men, да, похоже какая-то проблема на хостинге.
Я, к сожалению, сейчас в отпуске и вдали от хорошего интернета, так что починю, видимо, только 27го июня
Заказов не беру. Консультирую редко.
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Народ, кто уже скачал, поделитесь пожалуйста, а то хостинг не доступен
www.quatrox.ru
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Хостинг починил, архив доступен по старому адресу.
Приношу свои извинения за неполадки с хостингом.
Заказов не беру. Консультирую редко.
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Если сайт выполнен на HTML5, то для современных браузеров можно дополнительно ускорить загрузку, загружая скрипты асинхронно.
Для этого в файле min/hostcms_svc.php меняем 30-ю строчку:
$tmpl['js'] = '<script type="text/javascript" src="%s"></script>' . "\n";

на
$tmpl['js'] = '<script async type="text/javascript" src="%s"></script>' . "\n";

#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
kovaldo, способ хороший, но пока не для всех - async понимают только webKit-браузеры и Firefox. Опера в пролете.
Есть еще очень близкий по смыслу параметр defer - его понимают IE, Firefox и последние версии webkit. Опера опять в пролете.
Для максимального эффекта надо бы задавать оба, но мне не совсем понятно, что произойдет в браузере который поддерживает оба атрибута, потому как этими атрибутами по-разному определяется порядок выполнения скриптов на странице (об этом подробнее здесь) - по хорошему надо бы потестить все три варианта (acync, defer и acync defer)
По этой теме есть еще полезная информация здесь и здесь.
UPD: И еще вот здесь.
Заказов не беру. Консультирую редко.
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Что-нибудь выяснили по теме последнего поста?
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Ator, я проводил некоторые эксперименты, и пришел к выводу, что лучше всего старая добрая классика
Лучше всего размещать подключение javascript в самом конце документа, перед закрывающим тегом body. По сути такое размещение аналогично размещению в секции head с указанным параметром defer, но зато работает абсолютно везде и именно так как и было задумано.
Размещая javascript в конце html-документа параметр defer можно не указывать - в данном  случае и без него скрипты загрузятся последними.

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

С параметром async у меня как-то не сложилось - в разных браузерах разные результаты.

С сочетанием обоих параметров не тестировал.
Заказов не беру. Консультирую редко.
#
Re: Minify для HostCMS - объединение и сжатие скриптов и стилей
Код файла hostcms_svc.php обновлен до версии 1.1

Изменения:

  • Поддержка параметров defer и async для скриптов - при вызове функции getLink() для скриптов, вместо js нужно указать jsdefer или jsasync соответственно.
  • В ссылке формируемой функцией getLink() передача параметров теперь осуществляется на файл index.php в явном виде - это устраняет проблемы, проявляющиеся на некоторых хостингах, где используется связка Nginx + PHP-FPM


Репозиторий проекта выложен на BitBucket — теперь там можно всегда скачать последнюю версию, следить за изменениями и выходами апдейтов, а в разделе wiki можно прочитать самую последнюю версию инструкции по установке.
Скачивайте и следите за обновлениями! — https://bitbucket.org/JamesKotov/google-minify-for-hostcms-v.5/
Заказов не беру. Консультирую редко.
Авторизация