Про минимизацию javascript и css знают все. Ну если кто не знает, то, вкратце, это уменьшение объема файлов за счет удаления комментариев, разметки, переносов строк и прочего. Особенно актуально оно для интернет сайтов, которые при первом же визите пользователя должны порадовать его своей производительностью. Но наш проект, во-первых, работает в локальной сети, а во-вторых, используется на одних и тех же компьютерах изо дня в день, поэтому мы долгое время совсем не задумывались об оптимизации скриптов и стилей. Пока не стали плотно работать с ExtJS.
Созданная страничка со всеми подключенными скриптами и стилями весит больше 5 Мб (около 200 файлов). Одно только сгенерированное DOM-дерево в коде HTML содержит более 500 000 байт. Работать с системой пользователь может начать не раньше, чем через 5 секунд после загрузки страницы (инициализация скриптов, ExtJS и т.п.).
Как оказалось, несмотря на наличие локальной сети у заказчика и частую работу с одними и теми же страницами (должно же быть встроенное кэширование в браузере), иногда с загрузкой страниц возникают проблемы. Поэтому было решено уменьшить количество запросов к серверу и поработать над общей производительностью ExtJS в IE8.
Для минификации скриптов сначала скачал Google Closure Compiler, как один из самых популярных, да и корпорация добра плохого не сделает…
Google Closure Compiler
Положил файлик compressor.jar в папку со скриптами. Чтобы его запускать, пришлось поставить java. Сделал bat-файлик запуска с двумя командами, последняя из которых всего лишь делает задержку в 10 секунд, чтобы можно было успеть увидеть возможные ошибки и самому закрыть окно командной строки. Вот таким вот образом слил все скрипты в один файл, вес уменьшился примерно в полтора раза (это содержимое bat-файла):
cd %0..
java -jar compiler.jar --js=NavigationJS.js --js=SSSC.js (здесь еще куча файликов аналогичным образом) --js_output_file=bcr_master.min.js
ping -n 1 -w 100000 192.168.254.254 >nul
Все просто и элегантно, провозился минут пять. Команда cd %0.. в начале файла нужна для того, чтобы дальнейшее выполнение команд происходило внутри директории, в которой расположен сам .bat файл, а не с директории по умолчанию после запуска командной строки.
Но тут возникла идея минимизировать не только JS, но и CSS файлы, а Google Closure этого делать, увы, не умеет. Поэтому решил переделать все на YUI Compressor, о котором много отзывов, и он также сжимает CSS.
YUI Compressor
Для объединения всех файлов проекта был написан батник уже значительно большего объема, потому что этот YUI не умеет воспринимать в строке сразу несколько файлов — ему можно скармливать только по одному файлу. А значит, предварительно нам нужно слепить файлы в один временный файл командой copy, а уже потом его сжать юай компрессором.
Кстати, важное замечание — все объединяемые файлы javascript должны иметь в конце файла точку с запятой, а лучше с переносом на след.строку. Вообще любые операторы должны заканчиваться точкой с запятой, и решарпер люто негодует, когда видит наш javascript.
cd %0..
copy /b .....Scriptsjqueryautoresize.jquery.min.js + .....Scriptsjqueryjquery.nano.js + .....Scriptsjqueryjqueryslidemenu.js + .....ScriptsUnTreeTabs.js + .....ScriptsFixedHeader.js + .NavigationJS.js + .SSSC.js + .Filters.js + .Dictionaries.js + .EditResurce.js + .Calc.js + .Formula.js + .LoadExcel.js + .GetNSBFile.js + .SelectedTableColumns.js + .LoadMNT.js + .LoadNSB.js + .GetResInXLS.js + .WarningUnConfMNT.js + .Condor.js + .Bids.js + .SO.js combined.js
java -jar yuicompressor-2.4.8.jar combined.js --type js -o bcr_master_yui.min.js --charset cp-1251
del combined.js
copy /b .....Stylesjqueryjqueryslidemenubcr.css + .....BCRStylesTableBCR.css + .....BCRStylesKondor.css combined.css
java -jar yuicompressor-2.4.8.jar combined.css -o .....BCRStylesbcr_master_yui.min.css --charset cp-1251
del combined.css
copy /b .....ScriptsJSON.js + .....Scriptsmagix_expand.js + .....Scriptscollapse.js + .....klayers.js + .....Scripts.js + .....ScriptsExtFunction.js + .....ScriptsMPMessage.js + cookies.js + Common.js + .....Scriptsjqueryjquery.nano.js + .....Scriptsjqueryjqueryslidemenu.js + .....ScriptsUnTreeTabs.js + NavigationJS.js + SSSC.js + Filters.js + Dictionaries.js + EditResurce.js + Calc.js + LoadExcel.js + GetNSBFile.js + SelectedTableColumns.js + LoadMNT.js + LoadNSB.js + GetResInXLS.js + WarningUnConfMNT.js + Condor.js + SO.js + .....ScriptsFixedHeader.js + Formula.js + Bids.js combined.js
java -jar yuicompressor-2.4.8.jar combined.js --type js -o combined.min.js --charset cp-1251
copy /b combined.min.js + .....Scriptsjqueryjquery.blockUI.min.js + .....Scriptsjqueryjquery.cluetip.min.js + .....Scriptsjqueryjquery-tooltipjquery.tooltip.min.js + .....Scriptsjqueryjquery-tooltiplibjquery.bgiframe.min.js + .....Scriptsjqueryjquery-contextmenujquery.contextmenu.min.js + .....Scriptsjqueryjquery.AddIncSearch.min.js + .....Scriptsjqueryjquery-ui-timepicker-addon.min.js + .....Scriptsjqueryautoresize.jquery.min.js + .....Scriptsjqueryplugins.fileupload.min.js mbcrfull.min.js
del combined.min.js
del combined.js
copy /b .....Scriptsext.jsext-all-debug.js + .....Scriptsext.jslocaleext-lang-ru.js + .....Scriptsjqueryjqueryslidemenu.js + OM.js + History.Ext.js + RD.Ext.js + RD.js combined.js
java -jar yuicompressor-2.4.8.jar combined.js --type js -o page_RD.min.js --charset cp-1251
del combined.js
::copy /b .....StylesMPMessage.css + .....BCRStylesTableBCR.css + .....BCRStylesKondor.css combined1.css
::java -jar yuicompressor-2.4.8.jar combined1.css -o .....BCRStylesmbcrfull.min.css --charset cp-1251
::del combined1.css
::copy /b .....Stylesjqueryui.all.css + .....Stylesjqueryjquery.cluetip.css + .....Stylesjqueryjqueryslidemenubcr.css + .....Stylesjqueryjquery.MultiFile.css + .....Stylesjqueryjqueryslidemenu.css combined2.css
::java -jar yuicompressor-2.4.8.jar combined2.css -o .....Stylesjquerymbcrfull.min.css --charset cp-1251
::del combined2.css
::copy /b .....Stylesjqueryjquery.MultiFile.css + .....StylesTree.css + .....BCRStylesOM.css + .....Stylestooltip.css + .....Stylesjqueryjqueryslidemenu.css + .....BCRStylesRD.css combined.css
::java -jar yuicompressor-2.4.8.jar combined.css -o .....BCRStylespage_RD.min.css --charset cp-1251
::del combined.css
::ping -n 1 -w 100000 192.168.254.254 >nul
Так выглядит файл запуска компрессора в настоящее время. Как видите, строки минификации CSS закомментированы в силу специфики нашего проекта. На самом деле в минификации CSS есть масса тонкостей, а сливать их а один файл — задача не из легких:
- Во-первых, нужно тщательно следить за использованием относительных путей к изображениям. Стили ExtJS и других библиотек основаны на относительных путях, а значит они сразу выпадают из нашего объединения (кстати, в большинстве своем они уже минифицированы).
- Во-вторых, в CSS файлах могут встречать команды import. Это ад.
- В третьих, можно же создавать минифицированные объединенные стили отдельно в каждой из папок, а потом включать в проект, но, как выяснилось, таких файлов у нас получается не так уж много и прирост производительности будет небольшой. Поэтому решили минификацию CSS пока отложить. (Можно было и на Google Closure Compiler остановиться в таком случае)
А теперь самое интересное — батник у нас есть, объединенные скрипты генерируются успешно, осталось их прописать в релизной версии проекта. Все вроде работает, нужно коммитить…. каждый раз запуская скрипт.
Автоматизация минификации при коммите в релиз
Дело в том, что у нас две ветки в SVN — рабочая (DEV) и релизная. Каждый раз перед выкладыванием версии на сервер мы выполняем merge всех (ну или нужной части) изменений, билдим и только потом (если все нормально) коммитим. И надо, во-первых, не забывать самому постоянно выполнять этот батник перед коммитом в релиз, а во-вторых, следить за всеми разработчиками, чтобы тоже не забывали это делать.
И тут нам на помощь приходят Hook Scripts в TortoiseSVN!
В настройках клиента SVN заходим на вкладку Hook Scripts и выбираем там папку нашего проекта и сам батник. В опциях Hook Type выбираем «Start-Commit Hook«, чтобы скрипт запускался перед тем, как отобразится окно коммита.
Настройка запуска минификации перед коммитом
Вуаля, все работает и не надо ни за кем следить!
Есть, конечно, куча встроенных в visual studio средств объединения и минификации, но их тоже надо устанавливать на каждой машине, а еще в них тоже много тонкостей. До этого у нас использовался встроенный метод Composite Scripts, но он не обладает достаточной функциональностью в сравнении с теми же YUI или Google closure Compiler.
Автор: genixg