Използване на GZIP компресия
Компресирането на страниците при уеб сървъра е лесен и ефективен начин да спестиш трафик (bandwidth) и да намалиш значително времето, за което се зареждат страниците на твоя сайт. За да разбереш защо и кога ти трябва компресиране трябва да имаш елементарни познания по HTTP протокола и начина, по който си разменят данни браузъра и уеб сървъра.
HTTP Заявка и отговор
Когато в браузъра напишеш интернет адрес http://domain.com/index.html той изпраща запитване към уеб сървъра, който хоства сайта domain.com и протича разговор подобен на следния:
.
.
.
.
.
.
.
.
1. Браузър: Здрасти domain.com, дай ми index.html
2. Сървър: Добре, чакай да видя дали има такъв файл...
3. Сървър: OK намерих файла (response code 200 OK). Изпращам файла.
4. Браузър: Ох, 100KB? Зареждам... зареждам... готово целия файл е зараден и показан (Done).
Разбира се реалната картина е малко по-сложна. Тук не са написани всичките хедъри, които си разменят браузъра и уеб сървъра. Хедърите са служебна информация, която браузъра и сървъра разменят помежду си невидимо за потребителя на сайта. Хедърът "GET /index.html HTTP/1.1" се нарича хедър на заявка (request header), а хедъра с отговор на сървъра "HTTP/1.1 200 OK" се нарича хедър на отговор (response header). Името на домейна doamin.com е само за пример.
Преглед на HTTP хедъри
Има различни начини, да видиш всички хедъри, които си разменят браузърът и сървъра.
Ако използваш браузър Google Chrome тази възможност е вградена в браузъра - натисни клавишната комбинация Ctrl+Shift+I и екрана ще се раздели на две. Натисни третия бутон Network и след това зареди в браузъра сайта https://ganbox.com. Ще се зареди списък с елементи, които се съдържат в началната страница на ganbox.com, отиди в началото на списъка и избери с мишката първия елемент. Отдясно ако не е избран избери таб Headers и ще видиш всички изпратени и получени хедъри от браузъра. В раздела Request Headers се вижда, че браузъра е изпратил хедъра "Accept-Encoding: gzip,deflate,sdch". Всички съвременни браузъри изпращат този хедър, с което казват на сървъра, че могат да приемат компресирано съдържание. Щом могат, нека правим сайтовете си така, че да се възползваме от тази възможност.
Ако използваш браузър Mozilla Firefox ти трябва плъгина Live HTTP Headers. След като го инсталираш и рестартираш браузъра, този плъгин се включва от Tools / Live HTTP Headers и за всяка страница която зареждаш, ще виждаш хедърите.
Скорост на зареждане на сайт
Нека разгледаме как се разпределя времето за зареждане на страницата на всяка от стъпките. Най-бавно се пренасят данните от стъпка 3 към стъпка 4, след това по време е пренасянето на данните от стъпка 1 към стъпка 2, след което са самите стъпки в този ред: 3, 4, 2, 1. Както се вижда най-проблемна е сивата зона означена с Интернет през която преминават данните. Защо това е така? Защото тук се случват много неща. Ще изброя само тези, които имат отношение към статията: превръщане на името domain.com в IP адрес, установяване на TCP връзка между двата компютъра - този с браузъра и този на който е уеб сървъра, разделяне на файла на пакети, като всеки пакет се номерира и адресира, изпращане на пакетите. Колкото по-голям е обема на предаваните данни, толкова повече пакети се получават. Пакетите пътуват през мрежата, като преминават през междинни машини - рутери, ако браузъра и уеб сървъра са в една и съща държава междинните рутери са около 3, но ако е в друга държава може да се 5-6 и повече. Получаващата машина започва да получава пакетите, сглобява ги за да получи оригиналния файл. Възможно е някой от пакетите да се загуби и ще бъде изпратен повторно. За всеки от пакетите се изпраща потвърждение.
За пълнота ще спомена, че на стъпка 3, ако файла не е HTML, а PHP файл или друг скрипт, той може да има обръщение към SQL база данни, от която извлича данни. Ако SQL заявката е прекалено бавна, може да се получи така, че това да бъде най-бавната стъпка от всички. По този начин се вижда, че има само две места, на които можем да направим оптимизация - оптимизиране на SQL заявката и намаляване размера на файла, предаван от стъпка 3 към стъпка 4 и тъй като това не е статия за оптимизация на SQL заявки, няма да разглеждаме този случай, а само компресиране на файла за получаване на по-малък размер. Така стигаме до необходимостта, да се погрижим уеб сървъра да връща някои от файловете компресирани.
Компресиране на данни в HTTP отговор
Когато се ползва компресиране на данните, разговорът между браузъра и уеб сървъра изглежда така:
.
.
.
.
.
.
.
.
1. Браузър: Здрасти domain.com, искам да получа index.html, мога да получа компресирана версия, ако има.
2. Сървър: Добре, чакай да видя дали има такъв файл и виждам, че може да приемаш компресирани файлове.
3. Сървър: OK намерих файла (response code 200 OK). Компресирам и изпращам файла.
4. Браузър: Супер! Само 10 KB е, ще го разкомпресирам и покажа на потребителя.
Формулата е проста: по-малък файл = по-малък трафик = по-бързо зареждане на страницата => всички са доволни: потребителя защото отваря сайта бързо и собственика на сайта, защото плаща по-малко за трафик (ако има ограничение на трафика).
Тънкият момент при тази комуникация е браузърът и сървърът да се договорят, че ще се пренася компресирано съдържание за конкретния файл. Споразумението протича в две части:
- браузърът изпраща хедър "Accept-Encoding: gzip, deflate", с което казва на сървъра, че може да приема компресирани файлове, по gzip компресия или по deflate компресия;
- сървърът връща хедър "Content-Encoding: gzip", ако съдържанието наистина е компресирано.
Браузърът не може да задължи сървъра да върне компресирано съдържание, той само изпраща молба. Ако браузърът е казал, че приема компресирани файлове, но сървърът не върне "Accept-encoding" хедър, това означава, че сървърът по някаква причина не е компресирал съдържанието.
Кога да се ползва компресиране?
Най-важното е да разбереш, кога да ползваш компресирани файлове:
1. Компресират се само големи файлове! Ефективността зависи и от типа на файловете, но в най-честите случаи компресия трябва да се ползва за файлове с големина над 50-60 KB. За малки файлове, компресирането е неефективно и може да има отрицателен ефект.
2. Компресират се само текстови файлове с разширение: HTML, HTM, CSS, JS, TXT, XML, CSV и др. Не се компресират двоични файлове с разширения: JPG, PNG, GIF, PDF, DOC, XSL, MP3, AVI, MOV и др. Причината за това е, че двоичните файлове вече са компресирани и при опит да ги компресираме само ще натоварим уеб сървъра без да променим размера на файла.
Трябва да се има предвид, че използването на компресия натоварва уеб сървъра. Всяко компресиране на файл използва процесора на уеб сървъра и за силно посещавани файлове е възможно да се получи претоварване на сървъра, ако не сме предвидили подходящ хардуер или ако не са зададени подходящи настройки на уеб сървъра. Точно по тази причина хостинг доставчиците забраняват mod_deflate на споделен хостинг.
Настройки на сървъра
Пускането на компресиране на файловете на уеб сайт не е трудно, но трябва да знаем как е конфигуриран сървъра. За по-бързо ориентиране е добре да създадеш следния PHP файл:
<!--?php phpinfo(); ?-->
Качи файла и го изпълни, за да видиш информация за уеб сървъра. В този пример разглеждам Apache Version: Apache/2.2.14
Не е важно точно коя версия, важното е да започва с 2. Ако в "Loaded Modules" виждаш mod_deflate - това е най-добрия вариант, защото има включена поддръжка на deflate компресиране.
В този случай ти трябва да добавиш в .htaccess файла в главната уеб директория public_html (ако нямаш такъв файл го създай) следните редове:
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/x-javascript text/plain text/xml application/xml application/xhtml+xml application/rss+xml # за правилно обработване на заявки зад прокси Header append Vary User-Agent
Това е всичко. Изброени са типовете файлове, които трябва да се компресират, уеб сървъра сам проверява дали браузъра поддържа компресия и изпраща компресиран файл или не.
Споделен хостинг и компресиране
Ако използваш споделен хостинг почти сигурно ще имаш един от тези два проблема: забрана на ползване на mod_deflate или забрана за промяна на .htaccess файла. В този случай, ако в резултата от phpinfo() виждаш mod_gzip все още може да използваш компресия, като в началото на всеки php файл (например в header.php) още преди да е изпратен хедър или друго съдържание към уеб сървъра се поставя следния код:
if(extension_loaded('zlib')) { if(substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) { @ob_start("ob_gzhandler"); }else{ @ob_start(); } }
и съответно в дъното на всеки файл (например във footer.php) след изпращане на цялото съдържание към уеб сървъра добави следните редове:
if(extension_loaded('zlib')){ @ob_end_flush(); }
Като резултат на това PHP интерпретатора на сървъра проверява дали е изпратен от браузъра хедър "Accept-encoding" и ако това е така изпраща компресирана версия на файла.
За да провериш дали компресирането сработва може да използваш следния онлайн инструмент online gzip test. За съжаление това ще сработи само за PHP файловете и не за CSS или JS файлове. Това може да се види с инструмента на Chrome или при директно зареждане на CSS файл.
При зареждането на един PHP файл, уеб сървъра го подава на PHP интерпретатора, който го изпълнява и го превръща в чист HTML, който се изпраща към браузъра. Обикновено всеки HTML файл съдържа в себе си обръщение към други файлове, като например включване на CSS стилове или JavaScript файлове. Едва, когато браузърът започва да показва получения HTML файл и стигне до обръщение към друг файл, за всеки от тях изпраща нова HTTP заявка до уеб сървъра. На споделен хостинг ще се компресира само основния HTML файл без допълнително заредените CSS и JS.
За компресиране на други файлове се ползва следната техника за стриймване през PHP.
Например, ако в head частта на страницата се зарежда CSS файл със следния ред:
Създаваме файл style.css.php със същото съдържание като оригиналния файл style.css, след което в началото на файла поставяме кода:
<!--?php if(extension_loaded('zlib')){ob_start('ob_gzhandler');} header("Content-type: text/css"); ?-->
и в дъното на файла на последния ред поставяме:
<!--?php if(extension_loaded('zlib')){ob_end_flush();}?-->
По същия начин може да се стриймва и JavaScript файл с тази разлика, че вместо хедъра: header("Content-type: text/css"); се изпраща хедъра: header("Content-type: application/x-javascript");
Файлът style.css се подменя с файла style.css.php и реда в head блока става:
Ако този ред се ползва на много места в кода, вместо да се променя навсякъде, може да се направи заместване с mod_rewrite правилото:
RewriteRule ^style\.css$ /style.css.php [R=permanent,L]
Още веднъж напомням, че това има смисъл само за големи файлове над 60 KB, като средното намаляване на файловете е между 60% и 70% по-малки текстови файлове.
Други техники за оптимизация на CSS, JavaScript и картинки
- минимизиране на JavaScript-а например чрез http://www.minifyjavascript.com/. Това не е компресиране, но е премахване на коментари, празни редове и интервали и други излишни символи, което за дълъг файл също може да помогне. Важното е да пазиш оригиналната версия на файла, защото минимизираната много трудно се променя при нужда. Неудобството е, че след всяка промяна, ще трябва да минимизираш оригиналния файл отново.
- разделяне на файла на по-малки, като най-често ползваните функции се изнасят в common.js, а останалите в други файлове, като в отделните страници се зареждат само файловете които ни трябват. Може да се ползва и за CSS файлове, като може да се комбинира с другите методи.
- изнасяне на JS и CSS на поддомейн, заради премахване на бисквитките, като тук дори е по-важно да изнесем всички изображения на същия поддомейн. Ако твоя сайт е domain.com създай поддомейн i.doamin.com и там постави всички CSS, JS и файлове на изображения като JPG, GIF, PNG и др. Разбира се навсякъде в кода ще трябва да преправиш пътя до тези файлове. В резултат на това при зареждане на всеки от този файлове няма да се изпраща излишна информация за бисквитки. За WordPress има готов плъгин, който записва изображенията на поддомейн.
- кеширане на JS, CSS и картинки. Това са файлове, които се променят много рядко и спокойно можем за тях да зададем специален кеш контрол, който да ги кешира за дълъг период например година.
- използване на CSS спрайтове - техника, която обединява множество картинки от една страница в едно единствено изображение, от което с помощта на CSS показваме само отделни части на различните места, понеже премахва HTTP заявки и прави компресирането на изображението по-ефективно отколкото на всички сумарно, може да спести над 50% трафик от трафика за изображения.
Оптимизация на сайт
Преди да се реша да отделя от ценното си време и да напиша тази статия, потърсих за български статии на тази тема и за съжаление видях доста неточни статии на различни сайтове, които обясняваха нещо, които очевидно автора им не разбира добре. Предполагам статиите са били превеждани от английски само с цел SEO от хора, който не разбират достатъчно добре HTTP протокола. Това затвърди желанието ми да покажа как лесно и бързо да оптимизираш скоростта на зареждане на сайта си с използване на GZIP компресиране на страниците на сайта и най-важното - кога да го правиш и кога не.
Прочетена:22059
Просто нямам думи, с които да опиша, колко ценна е тази статия точно. Аз се чудих дали да пиша подобна. Но си помислих, че най-вероятно никой няма да прояви интерес, поради кодерската й насоченост. Но определено бях опроверган. Особено с всичките тези примери на код в нея. За съжаление те не говорят нищо на обикновените хора, които се интересуват от Оптимизация, но определено говорят много на хората като мен и теб. Ако искаш мога да споделя един сравнително добър плъгин пък, за Minify-ване.
Разбира се. Ще го добавя в текста.
Благодаря! Наистина на български нямаше нищо разбираемо и подробно написано по този въпрос. Доста се измъчих, докато намеря и информация на английски като за лаик като мен. Статията е чудесна!
-Много ми хареса статията, изключително полезна благодаря.
Поздравления за добрата статия, само да споделя още един минимизатор за js и css - YUI Compressor(developer.yahoo. com/yui/compressor/), който лесно може да се вгради в даден фреймуърк и при рилийз версията да ти минимизира нужните файлове.