- PVSM.RU - https://www.pvsm.ru -

Минификация CSS и Javascript в Website проекте ASP.NET

Про минимизацию javascript и css знают все. Ну если кто не знает, то, вкратце, это уменьшение объема файлов за счет удаления комментариев, разметки, переносов строк и прочего. Особенно актуально оно для интернет сайтов, которые при первом же визите пользователя должны порадовать его своей производительностью. Но наш проект, во-первых, работает в локальной сети, а во-вторых, используется на одних и тех же компьютерах изо дня в день, поэтому мы долгое время совсем не задумывались об оптимизации скриптов и стилей. Пока не стали плотно работать с ExtJS.

Созданная страничка со всеми подключенными скриптами и стилями весит больше 5 Мб (около 200 файлов). Одно только сгенерированное DOM-дерево в коде HTML содержит более 500 000 байт. Работать с системой пользователь может начать не раньше, чем через 5 секунд после загрузки страницы (инициализация скриптов, ExtJS и т.п.).

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

Для минификации скриптов сначала скачал Google Closure Compiler [1], как один из самых популярных, да и корпорация добра плохого не сделает…

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 [2]. Это ад.
  • В третьих, можно же создавать минифицированные объединенные стили отдельно в каждой из папок, а потом включать в проект, но, как выяснилось, таких файлов у нас получается не так уж много и прирост производительности будет небольшой. Поэтому решили минификацию CSS пока отложить. (Можно было и на Google Closure Compiler остановиться в таком случае)

А теперь самое интересное — батник у нас есть, объединенные скрипты генерируются успешно, осталось их прописать в релизной версии проекта. Все вроде работает, нужно коммитить…. каждый раз запуская скрипт.

Автоматизация минификации при коммите в релиз

Дело в том, что у нас две ветки в SVN — рабочая (DEV) и релизная. Каждый раз перед выкладыванием версии на сервер мы выполняем merge всех (ну или нужной части) изменений, билдим и только потом (если все нормально) коммитим. И надо, во-первых, не забывать самому постоянно выполнять этот батник перед коммитом в релиз, а во-вторых, следить за всеми разработчиками, чтобы тоже не забывали это делать.

И тут нам на помощь приходят Hook Scripts в TortoiseSVN!

В настройках клиента SVN заходим на вкладку Hook Scripts и выбираем там папку нашего проекта и сам батник. В опциях Hook Type выбираем «Start-Commit Hook«, чтобы скрипт запускался перед тем, как отобразится окно коммита.

Минификация CSS и Javascript в Website проекте ASP.NET
Настройка запуска минификации перед коммитом

Вуаля, все работает и не надо ни за кем следить!

Есть, конечно, куча встроенных в visual studio средств объединения и минификации, но их тоже надо устанавливать на каждой машине, а еще в них тоже много тонкостей. До этого у нас использовался встроенный метод Composite Scripts, но он не обладает достаточной функциональностью в сравнении с теми же YUI или Google closure Compiler.

Автор: genixg

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/48309

Ссылки в тексте:

[1] Google Closure Compiler: http://closure-compiler.appspot.com/home

[2] import: http://habrahabr.ru/users/import/

[3] Источник: http://habrahabr.ru/post/202102/