С недавних пор озаботился оптимизацией сайта. В частности решил свести количество подключаемых стилей и скриптов к минимуму. Я подключаю файлы через MinifyX. Для полного счастья осталось добавить подключение файлов дополнений. С этим я более менее справился. Но на разных страницах подключаются разные дополнения. И соответственно, для каждой страницы нужно подключать общие файлы и определённые файлы дополнений. Что в итого оказалось не очень удобно. Поэтому решил доработать MinifyX.

Первое, что я добавил — это группы. Они позволяют исключить дублирование источников. Таким образом, вместо полотенца файлов можно указать название группы. И если нужно изменить список подключаемых файлов, не нужно бегать по разным страницам или шаблонам. Достаточно скорректировать группу. Указывать группы нужно в файле core/components/minifyx/config/groups.php.

Следующая мысль — вместо вызовов на разных страницах сделать один вызов в главном шаблоне, а нужные файлы включать по условию. Сказано — сделано. Появились хуки. Это куски логики, которые можно внедрять в компонент. В качестве хуков можно указывать сниппеты или файлы. Хуки бывают двух типов — прехуки (вызываются до обработки файлов) и постхуки (вызываются после обработки файлов). Соответственно, в прехуках можно прописать логику добавления групп или файлов. Например, в сниппете указать общие для всех страниц стили и скрипты, а в хуке подключать требуемые для конкретной страницы.

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

А раз уж у нас есть доступ к скомпилированному файлу, грех не воспользоваться этим для передачи данных из MODX. Этого иногда очень не хватает, например, для инициализации javascript переменных. Т.е. в скрипте можно указать плейсхолдер MODX

// Файл scripts.js
var config = [[+config]];
...
А в хуке спокойно распарсить его. Особенно удобно это делать с помощью функции parse из библиотеки modHelpers.
if ($MinifyX->isJs()) {
    $content = parse($MinifyX->getContent(), ['config' => json_encode(['key'=>$object->getValue(),'user'=>$modx->user->id])]);
    $MinifyX->setContent($content);
}

Запомните!

MinifyX при обработке стилей вырезает теги MODX в квадратных скобках. Поэтому вместо них можно использовать фигурные скобки {{+key}}. И в функции parse() в третьем и четвертом параметре их указать.

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

if ($MinifyX->isJs()) {
    $jsCode = 'var config = ' . json_encode(['key'=>$object->getValue(),'user'=>$modx->user->id]) . ';';
    $content = $MinifyX->getContent() . $jsCode;
    $MinifyX->setContent($content);
}

Таким образом можно передавать информацию из MODX в javascript.

Информация!

Файловые хуки должны находиться в папке core/components/minifyx/hooks/.

Ещё я подумал, что было удобно иметь возможность несколько раз запускать сниппет с разными настройками. Например, один файл распарсить и подключить на страницу, а остальные собрать в один файл. Ещё эту фичу можно использовать для последовательного подключения. Т.е. собирать файлы, а подключать их только в последнем вызове. Например, в главном шаблоне указываете общие стили. А следующими вызовами добавляете остальные, но с другими настройками и хуками. Например, в одном вызове минифицируете, в другом только парсите. Делать это можно с помощью какого-нибудь своего параметра. Например, final:

// Вызываем в шаблоне
[[!MinifyX? 
    // ...
    &minifyCss => `1`,
    &cssGroups = `baseCss`,
    &hooks = `collect.php`
    &final = `0`
]]

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

[[!MinifyX? 
    // ...
    &minifyCss => `0`,
    &cssGroups = `newCss`,
    &hooks = `collect.php, parse.php`
    &final = `1`
]]

В постхуке, который нужно указывать во всех таких вызовах, прописываете логику:

# Файл collect.php
// Любые параметры сниппета доступны в $MinifyX->config
if (!$MinifyX->config['final']) {
    $MinifyX->tmp = default_if($MinifyX->tmp,'');
    $MinifyX->tmp .= $MinifyX->getContent(); // Сохраняем контент во временное свойство.
    $MinifyX->setFilename("");  // Отключаем сохранение файла.
} else {
    // Финальный вызов - выводим весь контент
    $data = $MinifyX->tmp . $MinifyX->getContent();
    $MinifyX->setContent($data);
}

Ещё пример. MinifyX регистрирует скомпилированные файлы через специальные методы MODX. Если нужно подключить файл точно в месте вызова сниппета с нужными HTML аттрибутами, то пишем такой хук:

<?php
$file = $modx->getOption('minifyx_cacheFolder') . $MinifyX->getFilename();
echo '<link rel="stylesheet" href="' . $file . '" type="text/css" media="screen" />';

Такая возможность была и раньше — через плейсхолдер. Но в данном случае можно управлять выводом, например, указывать HTML аттрибуты.

С версии 1.6.0 не актуально. В ней появились шаблоны и опция «print» для вывода тега файлов в месте вызова сниппета.

Как видно из примеров, в хуках доступен объект $MinifyX. У него есть методы для подключения как групп так и отдельных файлов.

Разработчикам эти возможности должны понравится. Остальные могут пользоваться минифаем как обычно — драг-н-дроп и указать файлы. Не надо портить себе нервы :)

Для тех, у кого возник вопрос — с какого перепуга я тут пишу про MinifyX, сообщаю: с недавних пор Василий, который bezumkin, отдал мне его в безмозмездное пользование. Теперь я за него отвечаю.

Для тех, кому показалось мало, читаем мой пост в сообществе.

Осталось только документацию поправить. Как будет время, соберусь и заставлю себя это сделать. А пока, ежели чё непонятно, спрашивайте.

20 января 2018, 15:38   436     0

Комментарии ()

    Вы должны авторизоваться, чтобы оставлять комментарии.

    Выделите опечатку и нажмите Ctrl + Enter, чтобы отправить сообщение об ошибке.