Главная » Полезные статьи » Разное » Оптимизация производительности в Drupal: сжатие страниц, файлов CSS и JavaScript с помощью GZIP
Распечатать статью

Оптимизация производительности в Drupal: сжатие страниц, файлов CSS и JavaScript с помощью GZIP

Недавно встал вопрос об оптимизации загрузки одного из моих сайтов. Помимо стандартных действий по увеличению производительности в Drupal: минимизации кода CSS и JavaScript, установки необходимых настроек на странице «Производительность», я решил уменьшить размер отдаваемых браузеру файлов и страниц сайта с помощью их сжатия.

После посещения множества сайтов и чтения кучи статей и комментариев я выяснил, что сжатие можно проводить двумя способами: с помощью средств сервера Apache или средствами PHP. Просмотрев настройки сервера на оптимизируемом сайте, оказалось, что на сервере не установлен модуль mod_gzip и mod_deflate, а значит использовать первый способ с Apache не приходится.

Пришлось снова лезть в Google и искать ответы на вопрос сжатия с помощью PHP. Все приведенные примеры сжатия были либо не применимы для Drupal, либо просто ужасны в реализации. В конце концов было сформировано решения на базе одного из методов.

Решения проблемы сжатия JS и CSS с помощью GZIP

Для того, чтобы включить сжатие JS и CSS файлов в Drupal, необходимо изменить два файла: .htaccess и index.php.

Изменения в .htaccess

В .htaccess нужно изменить стандартный для Drupal раздел переадресации на скрипт index.php. Вместо обычных двух строчек:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

нужно вставить следующий код:

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} ^.*\.(js|css)(\?.*)?$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Вообще весь код выполняет некоторую проверку запрашиваемого браузером адреса и при ее успешном прохождении производит переадресацию на файл index.php.

Теперь я объясню второй блок кода. В первой строке проверяется является ли запрашиваемый адрес файлом. Если адрес является существующим на сервере файлом, то в целом все условие становится ложным и переадресации на index.php не происходит.

По умолчанию следующие друг за другом условия RewriteCond соединяются логическим AND. В нашем случае нам необходимо использовать логическое OR, чтобы файлы js и css прошли по условию во второй строке. Для этого я поставил флаг [OR] в конце первой строки. Такой флаг объединяет логическим ИЛИ текущую и следующую строку. В третьей строке отсеиваются директории сервера.

Зачем нужна четвертая строка, если уже есть первая я так и не понял. Буду признателен, если кто-то объяснит это в комментарии к статье.

Пятая строка производит перенаправление на файл index.php при выполнении предшествующих ей условий. При этом вся часть адреса после имени домена передается в параметр q.

Изменения в index.php

После обработки сервером директив в файле .htaccess управление передается файлу index.php. В нем и будет происходить сжатие файлов и страниц сайта. Для осуществления этой жизненно необходимой процедуры нужно добавить в файл index.php перед всеми остальными выполняемыми строчками следующий блок кода:

01 <?
02 if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'))
03 // проверяется, поддерживает ли браузер сжатие gzip или x-gzip
04 {
05   if (!is_file($_GET["q"]))
06   // проверяется, является ли адрес похожим на файл
07   {
08     ob_start("ob_gzhandler"); // запускается обработка gzip для сжатия html-кода страниц сайта
09     header ("Content-Type: text/html; charset: UTF-8");
10     header ("Cache-Control: must-revalidate");
11     header ("Expires: " . gmdate ("D, d M Y H:i:s", time() + 60 * 60) . " GMT");
12   }
13   else if (preg_match("/^.*\.(js|css)(&\w+)?$/", $_SERVER["QUERY_STRING"], $ext))
14   // проверяется, является ли адрес похожим на файлы js или css
15   {
16     // часть следующего куска кода позаимствована из функции drupal_page_cache_header(), и необходима для кэширования сжатых файлов браузером.
17     $last_modified = gmdate('D, d M Y H:i:s', filectime($_GET["q"])) .' GMT';
18     $etag = '"'. md5($last_modified) .'"';
19  
20     $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE;
21     $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE;
22    
23     if ($if_modified_since && $if_none_match && $if_none_match == $etag && $if_modified_since == $last_modified)
24     {
25       header('HTTP/1.1 304 Not Modified');
26       header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
27       header("Etag: $etag");
28     }
29     else
30     {   
31       ob_start("ob_gzhandler");
32       $myme = array(
33         "css" => "text/css",
34         "js" => "text/javascript",
35       );
36       header ("Content-Type: ".(($myme[$ext[1]])?$myme[$ext[1]]:"text/html")."; charset: UTF-8");
37       header("Last-Modified: $last_modified");
38       header("ETag: $etag");
39       header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
40       header("Cache-Control: must-revalidate");
41       print file_get_contents($_GET["q"]);
42     }
43     exit;
44   }
45 }
46 ?>

Этот кусок кода я вставил перед строкой:

1 <?
2 require_once './includes/bootstrap.inc';
3 ?>

Если включено сжатие страниц на странице «Производительность» в настройках Drupal, то сжимать страницы самостоятельно не имеет смысла. И поэтому нужно оставить только код для сжатия JS и CSS файлов. Однако я все-таки предпочитаю отключать сжатие страниц Друпалом (так как оно как-то странно работает) и сжимаю их с помощью своего скрипта.

01 <?
02 if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'))
03 // проверяется, поддерживает ли браузер сжатие gzip или x-gzip
04 {
05   if (preg_match("/^.*\.(js|css)(&\w+)?$/", $_SERVER["QUERY_STRING"], $ext) && is_file($_GET["q"]))
06   // проверяется, является ли адрес похожим на файлы js или css
07   {
08     // часть следующего куска кода позаимствована из функции drupal_page_cache_header(), и необходима для кэширования сжатых файлов браузером.
09     $last_modified = gmdate('D, d M Y H:i:s', filectime($_GET["q"])) .' GMT';
10     $etag = '"'. md5($last_modified) .'"';
11  
12     $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE;
13     $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE;
14    
15     if ($if_modified_since && $if_none_match && $if_none_match == $etag && $if_modified_since == $last_modified)
16     {
17       header('HTTP/1.1 304 Not Modified');
18       header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
19       header("Etag: $etag");
20     }
21     else
22     {   
23       ob_start("ob_gzhandler");
24       $myme = array(
25         "css" => "text/css",
26         "js" => "text/javascript",
27       );
28       header ("Content-Type: ".(($myme[$ext[1]])?$myme[$ext[1]]:"text/html")."; charset: UTF-8");
29       header("Last-Modified: $last_modified");
30       header("ETag: $etag");
31       header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
32       header("Cache-Control: must-revalidate");
33       print file_get_contents($_GET["q"]);
34     }
35     exit;
36   }
37 }
38 ?>

Чего же я добился?

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

Результаты после включения механизмов сжатия HTML, CSS и JavaScript

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

Например, эта страница (где находится эта статья) была оптимизирована следующим образом:

Без сжатия Со сжатием GZIP Уменьшение размера файлов
HTML 37 КБ 10 КБ 370%
CSS 90 КБ 22 КБ 400%
JavaScript 465 КБ 150 КБ 310%
Страница целиком (с картинками) 654 КБ 244 КБ 268%

P.S. Тестирование передачи данных между сервером и браузером проводилось с помощью расширений Web Developer и Firebug для браузера Mozilla Firefox.

Источник:   w3pro.ru

Вы можете оставить комментарий, или обратную ссылку на Ваш сайт.

Оставить комментарий

Похожие статьи