Аптымізацыя прадукцыйнасці ў Drupal: сціск старонак, файлаў CSS і JavaScript з дапамогай GZIP

  1. Вырашэння праблемы сціску JS і CSS з дапамогай GZIP
  2. Змены ў .htaccess
  3. Змены ў index.php
  4. Чаго ж я дамогся?
Версія для друку

Нядаўна паўстала пытанне аб аптымізацыі загрузкі аднаго з маіх сайтаў. Акрамя стандартных дзеянняў па павелічэнню прадукцыйнасці ў 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 перад усімі астатнімі выкананымі радкамі наступны блок кода:

<? if (substr_count ($ _ SERVER [ 'HTTP_ACCEPT_ENCODING'], 'gzip')) // правяраецца, ці падтрымлівае браўзэр сціск gzip або x-gzip {if (! is_file ($ _ GET [ "q"])) // правяраецца, з'яўляецца Ці адрас падобным на файл {ob_start ( "ob_gzhandler"); // запускаецца апрацоўка gzip для сціску html-кода старонак сайта header ( "Content-Type: text / html; charset: UTF-8"); header ( "Cache-Control: must-revalidate"); header ( "Expires:". gmdate ( "D, d MYH: i: s", time () + 60 * 60). "GMT"); } Else if (preg_match ( "/^.* \. (Js | css) (& \ w +)? $ /", $ _SERVER [ "QUERY_STRING"], $ ext)) // правяраецца, ці з'яўляецца адрас падобным на файлы js або css {// частку наступнага кавалка кода запазычаная з функцыі drupal_page_cache_header (), і неабходная для кэшавання сціснутых файлаў браўзэрам. $ Last_modified = gmdate ( 'D, d MYH: i: s', filectime ($ _ GET [ "q"])). ' GMT '; $ Etag = ' "'. Md5 ($ last_modified). '"'; $ If_modified_since = isset ($ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE'])? stripslashes ($ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE']): FALSE; $ If_none_match = isset ($ _ SERVER [ 'HTTP_IF_NONE_MATCH'])? stripslashes ($ _ SERVER [ 'HTTP_IF_NONE_MATCH']): FALSE; if ($ if_modified_since && $ if_none_match && $ if_none_match == $ etag && $ if_modified_since == $ last_modified) {header ( 'HTTP / 1.1 304 Not Modified'); header ( "Expires: Sun, 19 Nov 1978 05:00:00 GMT"); header ( "Etag: $ etag"); } Else {ob_start ( "ob_gzhandler"); $ Myme = array ( "css" => "text / css", "js" => "text / javascript",); header ( "Content-Type:". (($ myme [$ ext [1]])? $ myme [$ ext [1]]: "text / html"). "; charset: UTF-8"); header ( "Last-Modified: $ last_modified"); header ( "ETag: $ etag"); header ( "Expires: Sun, 19 Nov 1978 05:00:00 GMT"); header ( "Cache-Control: must-revalidate"); print file_get_contents ($ _ GET [ "q"]); } Exit; }}?>

Гэты кавалак кода я ўставіў перад радком:

<? require_once './includes/bootstrap.inc'; ?>

Калі ўключана сціск старонак на старонцы "Прадукцыйнасць" у наладах Drupal, то сціскаць старонкі самастойна не мае сэнсу. І таму трэба пакінуць толькі код для сціску JS і CSS файлаў. Аднак я ўсё ж такі перавагу адключаць сціск старонак Друпалом (так як яно неяк дзіўна працуе) і сціскаю іх з дапамогай свайго скрыпту.

<? if (substr_count ($ _ SERVER [ 'HTTP_ACCEPT_ENCODING'], 'gzip')) // правяраецца, ці падтрымлівае браўзэр сціск gzip або x-gzip {if (preg_match ( "/^.* \. (js | css) (& \ w +)? $ / ", $ _SERVER [" QUERY_STRING "], $ ext) && is_file ($ _ GET [" q "])) // правяраецца, ці з'яўляецца адрас падобным на файлы js або css {// частку наступнага кавалка кода запазычаная з функцыі drupal_page_cache_header (), і неабходная для кэшавання сціснутых файлаў браўзэрам. $ Last_modified = gmdate ( 'D, d MYH: i: s', filectime ($ _ GET [ "q"])). ' GMT '; $ Etag = ' "'. Md5 ($ last_modified). '"'; $ If_modified_since = isset ($ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE'])? stripslashes ($ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE']): FALSE; $ If_none_match = isset ($ _ SERVER [ 'HTTP_IF_NONE_MATCH'])? stripslashes ($ _ SERVER [ 'HTTP_IF_NONE_MATCH']): FALSE; if ($ if_modified_since && $ if_none_match && $ if_none_match == $ etag && $ if_modified_since == $ last_modified) {header ( 'HTTP / 1.1 304 Not Modified'); header ( "Expires: Sun, 19 Nov 1978 05:00:00 GMT"); header ( "Etag: $ etag"); } Else {ob_start ( "ob_gzhandler"); $ Myme = array ( "css" => "text / css", "js" => "text / javascript",); header ( "Content-Type:". (($ myme [$ ext [1]])? $ myme [$ ext [1]]: "text / html"). "; charset: UTF-8"); header ( "Last-Modified: $ last_modified"); header ( "ETag: $ etag"); header ( "Expires: Sun, 19 Nov 1978 05:00:00 GMT"); header ( "Cache-Control: must-revalidate"); print file_get_contents ($ _ GET [ "q"]); } Exit; }}?>

Чаго ж я дамогся?

Дзякуючы гэтым ўдасканаленням я дамогся сціску большай частцы перадаюцца з сайта дадзеных. Ўжываць гэты механізм да медыя-файлаў тыпу малюнкаў або відэа не толькі бескарысна, але і небяспечна для прадукцыйнасці сервера.

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

Напрыклад, гэтая старонка (дзе знаходзіцца гэтая артыкул) была аптымізавана наступным чынам:

Без сціску Са сціскам GZIP Памяншэнне памеру файлаў HTML 37 КБ 10 КБ 370% CSS 90 КБ 22 КБ 400% JavaScript 465 КБ 150 КБ 310% Старонка цалкам (з малюнкамі) 654 КБ 244 КБ 268%

PS Тэставанне перадачы дадзеных паміж серверам і браўзэрам праводзілася з дапамогай пашырэнняў Web Developer і Firebug для браўзэра Mozilla Firefox.

Php?
Js | css) (\?. *)?
Php?
Quot;GMT"); } Else if (preg_match ( "/^.* \. (Js | css) (& \ w +)?
Quot;'; $ If_modified_since = isset ($ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE'])?
Stripslashes ($ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE']): FALSE; $ If_none_match = isset ($ _ SERVER [ 'HTTP_IF_NONE_MATCH'])?
Inc'; ?
Lt;?