Переписал MinifyX

Вчера озадачился улучшением скорости загрузки сайта и решил, что пора сжать скрипты и стили. Попробовал MinifyX - вроде ничего, но страшно уродует стили, а javascript фактически вообще не жмет (ну вырезал он переносы строк, и это все?). Ну хоть склеивает все файлы в один.

Затем в комментариях предложили другой способ. Он сканирует указанные директории на предмет наличия там скриптов и стилей, и пережимает. Только, CSS отчего то не жмет, и нет возможности указать конкретные файлы для обработки.

Да и в пакет не собрано - неудобно будет на другие сайты ставить. В общем, пришлось и от него отказаться.

По старой доброй традиции клонировал исходники MinifyX и принялся за работу. В исходниках, кстати, половины файлов нет - брал из пакета. Видимо репозиторий существет для галочки.

Сжатие

Первым делом выяснил, что в порче css виноват какой то матерый минификатор. В код не глядел, но судя по результатам работы - он анализиарует селекторы из css файлов и вырезает лишние, по его мнению. Конечно, размер файла становится меньше, но и сайт в итоге выглядет совершенно иначе.

Заменил его на библиотеку из проекта Minify, сразу стало хорошо. И минифицирует, и ничего не ломает.

В оригинальном MinifyX javascript вообще не сжимался. Ну то есть, вырезались переносы строк и все. Добавил обработку через JsMin.

Теперь, все сжимается просто прекрасно, никаких глюков не замечено. В этим покончили, надо переделать кэш.

Кэширование

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

Я решил поступить творчески - выкинул нафиг плагин и сделал нормальные имена у файлов, добавив к ним Unix timestamp параметром.

Если сниппет выполняется не кэшированным - timestamp всегда разный, и вы каждый раз грузите css и js заново. Хорошо для отладки.

Если же сниппет кэшированный - то ссылки на файлы выдаются со старым timestamp, и браузер берет файл из своего кэша.

При очистке кэша сайта чистится и кэш сниппета - а при первой загрузке страницы он выдаст новый timestamp, и вы загрузите новые css и js. Просто и красиво.

Но я пошел дальше. Если сниппет вызывается некэшированным, но файлы-исходники не менялись - то нет смысла их каждый раз обрабатывать, так? Тем более, там зверские регулярные выражения, что очень не быстро.

Поэтому, теперь при склейке файлов проверяется время изменения итогового файла и исходников. Если хоть один из исходных файлов (отдельно для css и jss) изменен - то склеиваем заново. Если нет - ничего не делаем.

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

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

Да, по поводу имен - добавлено 2 новых параметра:

  • &jsFilename - базовое имя файла, без расширения. По умолчанию - sсripts

  • &jcssFilename - базовое имя файла, без расширения. По умолчанию - styles

Вот эти имена в итоге и транформируются в такое:


/inc/min/styles.min.css?1347183340
/inc/min/scripts.min.js?1347183340

В общем, кэширование работает без всяких плагинов, просто, прозрачно и красиво, как я люблю.

По мелочи

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

Настройке те же (плюс 2 новые), только теперь оно действительно работает! Например, на этом сайте - загляните в исходный код.

Пример вызова на этом сайте:

[[MinifyX?
    &minifyCss=`1`
    &minifyJs=`1`
    &cacheFolder=`/inc/min/`
    &jsSources=`
        /inc/js/jquery-1.8.1.min.js
        ,/inc/js/jquery-ui-1.8.23.custom.js
        ,/inc/js/jquery.cookie.min.js
        ,/inc/js/jquery.fancybox.min.js
        ,/inc/js/jquery.mousewheel.min.js
        ,/inc/js/bootstrap.min.js
        ,/inc/js/prettify/prettify.js
        ,/inc/js/main.js
    `
    &cssSources=`
        /inc/css/bootstrap.min.css
        ,/inc/css/bootstrap-responsive.css
        ,/inc/css/reboot-landing.css
        ,/inc/css/reboot-landing-responsive.css
        ,/inc/css/jqueryui/jquery-ui-1.8.16.custom.css
        ,/inc/css/font-awesome.css        
        ,/inc/css/fancybox/jquery.fancybox.css
        ,/inc/js/prettify/prettify.css
        ,/inc/css/main.css
    `
]]
[[+MinifyX.css]]
[[+MinifyX.javascript]]

Javascript советуют переносить в подвал, чтобы резче грузилось.

Как обычно, прошу сообщать о найденных глюках и проблемах.

Важный update

Как оказалось, браузеры не кэшируют скрипты стили, если у них есть параметры в url, типа scripts.min.js?1234567890. А вот изображения с параметрами, почему то, прекрасно кэшируются.

В общем, пришлось переписать генерацию файлов так, чтобы timestamp был в имени - scripts_1234567890.min.js.

Крайне рекомендую обновиться на версию 1.1.2, ваш сайт забегает еще быстрее.

Следующая заметка →
Форкнул BannerX под именем BannerY, 1.0.0
Комментарии (61)
vancheloИван Брежнев
09.09.2012 12:08

Красота) Вы как всегда на коне

Shin
09.09.2012 12:54

Отличная новость. Попробую поставить.

А как насет плагина для сжатия html кодаа страницы?

bezumkinВасилий Наумкин
09.09.2012 13:02

Считаю, что не имеет смысла.

Экономия в 5-10 килобайт и лишняя обработка каждой страницы после очистки кэша.

Лучше настроить nginx, чтобы отдавал весь контент в gzip — выхлопа гораздо больше.

Denys Butenko
10.09.2012 20:19

Подскажите, сработает путь вида http:// или просто //yandex.ru/example.js?

bezumkinВасилий Наумкин
11.09.2012 01:12

Неа.

1. У такого файла не измерить filemtime — и будет непонятно, изменен он, или нет.

2. Файл может оказаться недоступен и загрузка страницы подвиснет. Чтобы отваливаться по таймауту, можно, конечно, написать запрос через CURL, но он не у всех есть.

Поэтому, файлы работают только локальные.

Denys Butenko
11.09.2012 16:09

У меня ошибка, при включенном jsMin появляется ошибка «Unexpected token ) », если отключить пропадает. Подключенные файлы:

/assets/templates/bs/js/libs/jquery-1.7.2.min.js ,/assets/templates/bs/js/libs/bootstrap/bootstrap.min.js

,/assets/templates/bs/js/libs/jquery-ui-1.8.23.custom.min.js

,/assets/templates/bs/js/libs/jquery.form.js

,/assets/templates/bs/js/libs/jquery.colorbox-min.js

,/assets/components/msearch/js/mfilter.js

,/assets/components/likedislike/js/web/likedislike.js

,/assets/templates/bs/js/script.js

bezumkinВасилий Наумкин
11.09.2012 16:12

Бывает, пока не понял отчего. Видимо, не все скрипты нормально работаю в куче с другими.

Подключайте по одному скрипту и выясняйте, кто виноват.

У меня сегодня на одном сайте была проблема с jquery.form. Перекачал его с родного сайта, несжатый — заработало.

Denys Butenko
11.09.2012 16:13

Спасибо за наводку, буду искать)

bezumkinВасилий Наумкин
11.09.2012 16:16

Очень советую качать все с родных сайтов. Яндекс на своем cdn явно как то их интересно пережимает, например.

Denys Butenko
11.09.2012 16:40

Так и делаю, с Яндекса только кнопка «Поделиться».

Обновил colorbox на полную версию, jquery form, bootstrap не минифицированный указал, ошибка пропала)

bezumkinВасилий Наумкин
11.09.2012 17:01

Клево!

Выходит, переминифицировать минифицированные скрипты нежелательно =)

bezumkinВасилий Наумкин
11.09.2012 16:18

Ну и попробуйте не пережимать уже пережатые скрипты (хотя у меня работает, на жтом сайте =))

Скачайте все несжатые, от производителя.

Denys Butenko
11.09.2012 17:09

Чтобы не заводить новый вопрос о оптимизации, спрошу здесь.

Запустил PageSpeed от гугла, говорит, что css и js файлы hypercomments можно ужать более чем на 70% если включить gzip или deflate, но как его включить для внешних ресурсов?

bezumkinВасилий Наумкин
11.09.2012 17:20

Я так понимаю, что никак.

Параметр deflate, думаю, можно указать, а вот gzip зависит от сервера. Попробуйте сохранить у себя и грузить локально.

Denys Butenko
13.09.2012 17:35

Следующие кэшируемые ресурсы имеют короткий срок действия.

В дальнейшем следует указать для следующих ресурсов срок действия не менее недели:

../scripts_1347387573.min.js (не указан срок истечения действия)

../styles.min.css (не указан срок истечения действия)

До этого кешировалось все нормально)

bezumkinВасилий Наумкин
13.09.2012 17:41

Сжатие то тут при чем?

Срок действия выдает веб-сервер, заголовками. Протестируйте этот сайт и посмотрите, что покажет.

bezumkinВасилий Наумкин
13.09.2012 17:51

У меня этим вопросом занимается nginx. Вот конфиг кэширования статики:

# serve static files directly

location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|bmp|woff)$ {

access_log off;

expires 10d;

break;

}

Denys Butenko
13.09.2012 20:19

Спасибо, разобрался)

Дмитрий Ломакин
02.10.2012 15:54

Про: «Вот эти имена в итоге и транформируются в такое:

/inc/min/styles.min.css?1347183340

/inc/min/scripts.min.js?1347183340»

Наткнулся на момент:

Если папка "/inc/min" не существует, то автоматически она не создается и MinifyX не создает файлы.

В логах ошибка есть:

[2012-10-02 10:49:46] (ERROR @ /index.php) [MinifyX] Could not write JS cache file!

[2012-10-02 10:49:46] (ERROR @ /index.php) [MinifyX] Could not write CSS cache file!

Предлагаю создавать папку автоматически.

bezumkinВасилий Наумкин
02.10.2012 16:11

При установке создается директория /assets/components/minifyx/cache/ каковая является директорией по умолчанию.

Меняете умолчание — создайте и директорию. Совсем уже разленились, блин.

Дмитрий Ломакин
02.10.2012 17:19

Не соглашусь.

Вопрос не в лени, вопрос в поиске ошибки, когда «все не работает»

Could not write JS cache file! — не информационно

Если бы в логах было «path „/inc/min“ for write JS cache file not found» было бы проще найти в чем косяк. А если компонента сама создаст нужную ей папку, то программисту будет житься проще.

Чем сложнее ошибку найти, тем выше порог вхождения в технологию.

Мне кажется MODX заслуживает гораздо более широкого распространения, чем сейчас. И Вы своими работами можете поспособствовать распространению MODX, а можете и не способствовать.

Цель моего поста отнюдь не «Безумкин, ты офигел так фигово писать»

Его смысл «Давайте сделаем сделаем MODX доступнее.»

Ваши знания на сегодняшний день весьма превышают мои в этом вопросе, Но я хотел помочь. Если мое участие впредь не требуется, дайте, пожалуйста, об этом знать прямо. Спасибо.

bezumkinВасилий Наумкин
02.10.2012 17:21

Жду ваших коммитов на Github.

Дмитрий Ломакин
02.10.2012 17:41

Мой уровень прикладное программирование, а не системное.

Я потенциальный пользователь ваших разработок, а не соразработчик. Увы.

Мордынский Николай
14.02.2013 11:28

Василий День добрый. В тему ускорения работы сайтов Наткнулся на весьма интересную вещь - для меня было в новинку. Использование в CSS вместо ссылок на изображение непосредственно base64 кода самого изображения. Вот статья на хабре, там есть скриптик который конвертирует CSS можно прикрутить к minify если заинтересует.

Из любопытства конвертировал картинку размером 270кб , текстовый файл с кодом 64 1кб.

Не относитесь критично ... просто решил поделится мало ли.)

bezumkinВасилий Наумкин
14.02.2013 11:43

Спасибо, интересно.

Можно, в принципе, всякие логотипы так сконвертить на досуге.

inetloverАлександр Наумов
21.02.2013 15:16

Отличное дополнение, спасибо! Только вот никак не могу найти настройки, те что указаны на скриншоте.

В настройках системы у меня их нет, все на несколько раз обыскал:

Подскажите, пожалуйста, где находятся настройки?

bezumkinВасилий Наумкин
21.02.2013 15:42

Это в параметрах самого сниппета.

inetloverАлександр Наумов
21.02.2013 15:47

О, спасибо большое - нашел!

Borisov Andrey
19.06.2013 03:30

Василий приветствую!

Хороший получился компонент, возможно будет интересно с чем столкнулся в процессе использования MinifyX при адаптации купленного html шаблона.

Есть скрипты которые подключаются в шапке и подвале сайта, снипет в таком случае выдает один и тотже результат, приходится делать "копию" снипета и менять все примерно в таком ключе:

getService('minifyx1','MinifyX', MODX_CORE_PATH.'components/minifyx/model/minifyx/',$scriptProperties); if (!($minifyX1 instanceof MinifyX)) return '';

$minifyX1->minify();

return '';

Тогда вызов работает. Собственно очень интересно узнать следующее:

1) Возможно ли сделать вызов одного и тоже снипета (без копирования и дописывания) но с разными параметрами (списками фалов, папкой кэша, наименованием файла скриптов и стилей)? 2) Возможно ли доработать на раздельные методы, которые бы просто возвращал значение имени "склеенного" js файла и css файла?

bezumkinВасилий Наумкин
19.06.2013 03:33

Все возможно, но пока я очень занят.

Как дойдут руки - буду делать.

Vlad
06.07.2013 03:23

Invalid argument supplied for foreach() in W:\html\aerosystems.ru\www\core\components\minifyx\model\minifyx\minifyx.class.php on line 151

Такая вот ошибка.

Ilya Ev
21.10.2013 17:39

да у меня тоже такая есть ERROR @ public_html/core/components/minifyx/model/minifyx/minifyx.class.php : 151) PHP warning: Invalid argument supplied for foreach()

Chero
20.10.2013 10:20

Было бы здорово добавить вот такой функционал:addheaderfilesВ сущности у афтора есть и плагин для минификации.

Chero
09.11.2013 14:15

Добрый день, при минификации вырезаются некотороые пробелы, например строка:

c.innerHTML="\x3c!--[if gt IE "+ ++b+"]

при минификации превращается в :

c.innerHTML="\x3c!--[if gt IE "+++b+"]

тут сократился пробел между +, что приводит к ошибке в минифициорованном коде.

есть ли какое-то решение? если не для плагина, то может этот код можно поправить?

bezumkinВасилий Наумкин
09.11.2013 14:22

Минифицирует Google Minify - все вопросы к нему.

Ну а вообще, в планах есть обновление и переделка пакета, может и эта проблема исчезнет.

Chero
09.11.2013 14:42

Да, не, вроде бы не Google Minify, а вот это используется: https://github.com/rgrove/jsmin-php/

Если кому понадобится, можно просто код поменять:

c.innerHTML="\x3c!--[if gt IE "+ (++b)+"]
bezumkinВасилий Наумкин
09.11.2013 14:43

Я давно делал, уже и не помню.

Но к переписыванию готовлюсь =)

Chero
09.11.2013 14:45

)) спасибо Тут кстати автор порекомендовал на какие минификаторы лучше перейти: https://github.com/rgrove/jsmin-php/может что-то приглянется

bezumkinВасилий Наумкин
09.11.2013 15:01

Для php там ничего нет, к сожалению.

Я вот сюда поглядывал, вроде перспективная библиотека.

164787961Серго Арбузов
22.11.2013 07:01

При установке с нуля MS2 и нового бутстрапа с MinifyX темы полностью калечатся. Вот, например, карточка товара выглядит примерно так

Как побороть сей досадный баг ?

bezumkinВасилий Наумкин
22.11.2013 07:25

Переписать чанки на Bootstrap3?

164787961Серго Арбузов
22.11.2013 07:32

Было бы очень круто! :) Так как я понятия не имею куда копать ! :(

sidarvikДарья Брандина
29.11.2013 21:32

Василий, подскажите, где именно нужно делать вызов этого сниппета?

Ruslan Jn
01.02.2014 19:28

Судя по всему в чанке head тут посмотрите http://rtfm.modx.com/extras/revo/minifyx

sergantСергей Шлоков
02.02.2014 05:55

Если через плейсхолдеры, то понятно дело, в секции head. А так в любом месте. При парсинге все подставится куда нужно.

Чикин Артур
02.02.2014 06:08
sergantСергей Шлоков
02.02.2014 06:22

Там не ответа на этот вопрос. А для начинающих было бы неплохо написать где нужно вставлять вызов этого сниппета.

bezumkinВасилий Наумкин
02.02.2014 06:51

Где в шаблоне скрипты и стили? Там и нужно вставлять, по моему - это очевидно.

Чем больше пишу и рассказываю, тем более странные вопросы задают. Скоро будет "а как зайти в админку?", "а что такое логин и пароль?".

sergantСергей Шлоков
02.02.2014 07:27

Чем больше пишу и рассказываю, тем более странные вопросы задают.

Еще древние философы писали: "Чем больше я знаю, тем больше я не знаю!" Чем больше ты рассказываешь, тем человеку интереснее, тем больше он задумывается и больше у него возникает вопросов. :) > Где в шаблоне скрипты и стили? Там и нужно вставлять, по моему — это очевидно.

А можно и не там. ;)

Дмитрий Васильев
31.03.2014 15:12

После установки пакета при очистке кеша сайта из админки в консоле начало появляться сообщение об ошибке: PHP warning: mkdir() [function.mkdir]: Invalid argument PHP warning: mkdir() [function.mkdir]: Invalid argument PHP warning: mkdir() [function.mkdir]: Invalid argument PHP warning: mkdir() [function.mkdir]: Invalid argument PHP warning: mkdir() [function.mkdir]: Invalid argument

MODX Revolution 2.2.13-pl (traditional) MinifyX 1.3.0 beta установлена из официального репозитория

Это у меня что не так или устарело где?

Дмитрий Васильев
31.03.2014 15:15

И вдобавок файлы в кеше появляются, но появляются пустыми :( Т.е. ссылки в head на файлы вставляются, файлы доступны, но они пусты: и js, и css

Можете подсказать куда смотреть? Спасибо.

ilyautkinИлья Уткин
31.03.2014 15:24

Версия php у вас какая?

Дмитрий Васильев
31.03.2014 15:26

PHP Version 5.3.13

На счёт пустых файлов прошу прощения - моя ошибка. Ошибся в путях - снипет не находил файлы для сжатия. А сообщение при очистке кеша ещё есть.

Дмитрий Васильев
31.03.2014 15:38

Добавлю, что даже при этой ошибке в логе консоли кеш очищается - старые файлы стилей и скриптов удаляются. Если это просто warning и можно на него не обращать внимания, то ладно. Смущает просто.

Дмитрий Васильев
31.03.2014 16:07

Покопался в коде minifyX. Заметил вызовы с указанием прав, может дело в них?

mkdir($dir, 0777, true) mkdir($this->cacheDir, 0755, true)

Дмитрий Васильев
31.03.2014 15:59

И возник ещё один простой вопрос: а кто и когда удаляет старые файлы скриптов и стилей в кэше?

bezumkinВасилий Наумкин
27.06.2014 18:49

Ты, когда чистишь кэш сайта.

Павел Голубев
25.06.2014 17:17

Если в JS есть 'use strict'; то валится вот такая ошибка

Fatal error: Uncaught exception 'RuntimeException' with message 'Unclosed string. in /core/components/minifyx/munee/tedivm/jshrink/src/JShrink/Minifier.php:409

bezumkinВасилий Наумкин
27.06.2014 18:49

Судя по пути, вопрос не ко мне.

Andrey
19.11.2014 13:25

Добрый день! при любом вызове minifyx 1.3.1 ошибка: minifyx.class.php on line 112 Parse error: syntax error, unexpected T_STRING - не нравится косая черта minifyx.class.php on line 112 Warning: Unexpected character in input: '\' (ASCII=92) state=1. Я так понимаю дело в версии php (у меня PHP Version 5.2.17)???

112 строчка: $Request = new \Munee\Request($options);

bezumkinВасилий Наумкин
19.11.2014 14:09

Пора обновить свой PHP хотя бы до 5.3.

bezumkin
Василий Наумкин
30.06.2022 03:58
Есть ли возможность формировать "friendly URL aliases", используя аналог translit MODx? ...
bezumkin
Василий Наумкин
27.06.2022 03:32
Спасибо за исправления, очень выручаешь =) Но учитывая количество не описаных в заметке дополнительн...
bezumkin
Василий Наумкин
27.06.2022 03:10
что будет использоваться для вывода многоуровневого меню Посмотри как работают комментарии на этом ...
bezumkin
Василий Наумкин
25.06.2022 11:56
Поправил, спасибо!
bezumkin
Василий Наумкин
22.06.2022 10:08
Я обычно не пользуюсь RTE редакторами, потому что они пишут всякое непонятное что в HTML. Но можно в...
bezumkin
Василий Наумкин
21.06.2022 01:58
onLoad(data) { this.total = data.total }, и onLoad({total}) { this.total = total }, В нашем случ...
bezumkin
Василий Наумкин
20.06.2022 14:01
Прекрасно тебя понимаю, я когда сам в этом разбирался - голова дымилась. Но зато теперь прямо-таки п...
bezumkin
Василий Наумкин
20.06.2022 09:30
Не надо, оно по умолчанию так - я просто чуть более подробно написал.
bezumkin
Василий Наумкин
19.06.2022 13:42
А можно же из 1 файла сделать 2 экспорта. По-умолчанию, и отдельно для футера: export const Footer =...
bezumkin
Василий Наумкин
19.06.2022 09:44
Тебе спасибо, что поддерживаешь рублём мои начинания!