Jump to content
Sign in to follow this  
lifestar

Сжимаем css и js

Recommended Posts

Итак, по просьбам трудящихся, раскрываю секреты, как работать с gzip архивами файлов стилей и ява скриптов, что позволит нам ускорить загрузку сайта. Сжатие на лету расматривать не буду, ибо смысла производить одинаковые операции, потребляющие ресурсы процессора каждый раз при загрузке сайта я не вижу.

Для начала научимся правильно вызывать эти файлы.

Предположим мы имеем файл style.css, который весит 19Кб. Для того, чтобы при открытии страницы сайта этот файл каждый раз не загружался, нужно дать указание браузеру положить его в кэш, причём надолго. Что же делать, если мы этот файл изменили? Ведь браузер так и будет брать старый файл из своего кэша и даже не посмотрит на ваш новенький вариант ;) Ключевое слово - вариант или версия. Итак, давайте к имени вызываемого файла добавлять версию и если что-то в нём меняем, то соответственно не забываем менять и версию.

Теперь внимание! Меняем исключительно строку вызова файла, но не имя самого файла. Тем самым экономим время, ведь нам не придётся менять название и файла.

Получаем следующий код в секции <head> вашего сайта:

<link rel="stylesheet" href="/templates/xLight/css/style.v1.0.css" type="text/css" />
, то есть версия css файла у нас первая. Но сам файл у нас физически лежит по адресу /templates/xLight/css/style.css. xLight- название вашего шаблона. Поехали далее. Делаем архивную копию нашего style.css. Для этого я использую бесплатную программу 7-Zip, у меня версия программы 4.57. Работаем точно так же, как и любыми другими архивами, например ZIP. Вот как это будет выглядеть 7z.png Итак, мы получили файл style.css.gz который теперь весит 4Кб. Сжали файл на 475% :) Далее я столкнулся в проблемами. По мануалу должна срабатывать следующая конструкция в .htaccess
RewriteCond %{HTTP:Accept-Encoding} gzip

RewriteCond %{REQUEST_FILENAME}.gz -f

RewriteRule ^(.*)$ $1.gz [QSA,L]
то есть если браузер понимает gzip и существует сам файл - отдаём. Однако FF2 по неизвестным мне причинам предлагает файл style.css.gz сохранить :) Вероятно в моих знаниях существует некий пробел... Тут нам на помощь приходит PHP :) В результате некоторых экспериментов было найдено 2 решения, какое из них более правильное я не знаю, предлагаю обсудить. Решение 1. PHP ONLY В папке css вашего шаблона в файл .htaccess дописываем необходимые нам строки, в результате чего мы должна получить следующий листинг:
Order Deny,Allow

Allow from all


RewriteEngine on

RewriteRule ^(.*\.)v[0-9\.]+\.css$	index.php?$1css [L]
Команда RewriteRule перенаправляет все запросы в эту папку на файл index.php, попутно вырезая новер версии. Файл index.php выглядит следующим образом:
<?php


define('CSS_DIR', $_SERVER['DOCUMENT_ROOT'].'/templates/xLight/css/');

$filename = $_SERVER['QUERY_STRING'];

if($filename != '')

{

	// Если браузер умеет работать с gzip и это не Safari и не Konqueror и есть сжатый файл - отдаём его, иначе несжатый

	if(strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false &&

	   strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') === false &&

	   strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') === false &&

	   file_exists(CSS_DIR.$filename.'.gz'))

	{

		$css = file_get_contents(CSS_DIR.$filename.'.gz');

		header('Content-Encoding: gzip');

		header('Content-type: text/css');

		// Кэшируем на год

		header('Cache-Control: max-age=31536000, public');

		header('Expires: '.gmdate('D, d M Y H:i:s', time()+31536000).' GMT');

		print $css;

	}

	elseif(file_exists(CSS_DIR.$filename))

	{

		$css = file_get_contents(CSS_DIR.$filename);

		header('Content-type: text/css');

		print $css;

	}

	else e404();

}

else e404();


function e404()

{

	header ("HTTP/1.0 404 Not Found", true, 404);

	echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

	<html><head>

	<title>404 Not Found</title>

	</head><body>

	<h1>Not Found</h1>

	<p>The requested URL '.$_SERVER['REQUEST_URI'].' was not found on this server.</p>

	<hr>

	'.$_SERVER['SERVER_SIGNATURE'].'

	</body></html>';

	die();

}


?>
В нём мы проверяем умеют ли наш браузер работать с gzip, а так же наличие самого файла .gz, ну и выдаём кэширующие заголовки. Если файла вообще нет, то эмулируем ошибку 404 :) Вариант рабочий. Решение 2. HTACCESS + PHP Вариант альтернативный. .htaccess
Order Deny,Allow

Allow from all


RewriteEngine on

# Вырезаем версию

RewriteRule ^(.*\.)v[0-9\.]+\.css$	$1css


RewriteCond %{HTTP:Accept-Encoding} gzip [OR]

RewriteCond %{HTTP:TE} gzip

RewriteCond %{HTTP_USER_AGENT} !Safari

RewriteCond %{HTTP_USER_AGENT} !Konqueror

RewriteCond %{REQUEST_FILENAME}.gz -f

RewriteRule ^(.*)\.css$	$1.css.gz

<FilesMatch ".gz$">

	AddHandler application/x-httpd-php .gz

	php_value auto_prepend_file index.php

</FilesMatch>
и index.php
<?php


define('CSS_DIR', $_SERVER['DOCUMENT_ROOT'].'/templates/xLight/css/');

// Обрабатываем полученную строку

$filename = str_replace('/templates/xLight/css/', '', $_SERVER['SCRIPT_NAME']);


if($filename != '' && $filename != 'index.php')

{

	$css = file_get_contents(CSS_DIR.$filename);

	header('Content-Encoding: gzip');

	header('Content-type: text/css');

	// Кэшируем на год

	header('Cache-Control: max-age=31536000, public');

	header('Expires: '.gmdate('D, d M Y H:i:s', time()+31536000).' GMT');

	print $css;

}

else e404();


function e404()

{

	header ("HTTP/1.0 404 Not Found", true, 404);

	echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

	<html><head>

	<title>404 Not Found</title>

	</head><body>

	<h1>Not Found</h1>

	<p>The requested URL '.$_SERVER['REQUEST_URI'].' was not found on this server.</p>

	<hr>

	'.$_SERVER['SERVER_SIGNATURE'].'

	</body></html>';

	die();

}


die();


?>
По сути тоже самое, однако почему то выдаёт на несколько десятков байт меньше. Всё. С .js файлами работаем по аналогии, единственно, что хочу заметить, что неплохо было бы минимизировать сам .js файл перед сжатием. PS Если на вашем хостинге работают модули апача mod_headers и mod_expires, то заголовки лучше выдавать ими, примерно так
Header set Cache-Control "max-age=29030400, public"

Header add Content-Encoding "gzip"

ExpiresActive On

ExpiresDefault A29030400
Это в .htaccess Можем и подстраховаться от ошибки 500 (вдруг модули выключат), тогда код такой:
<IfModule mod_headers.c>

Header set Cache-Control "max-age=29030400, public"

Header add Content-Encoding "gzip"

</IfModule>

<IfModule mod_expires.c>

ExpiresActive On

ExpiresDefault A29030400

</IfModule>

Удачных опытов :)

Edited by Александр Медведев

Share this post


Link to post
Share on other sites

Спасибо! полезная статья. Пошел эксперементировать)

Share this post


Link to post
Share on other sites

Спасибо! Рад что среди участников форума есть люди, которые думают в нужном направлении :)

Есть пара идей, как освобожусь напишу в личку...

Share this post


Link to post
Share on other sites

Отличный мануал, спасибо :)

Share this post


Link to post
Share on other sites

ок, тоже спасибо, возьму на заметку

Share this post


Link to post
Share on other sites

Спасибо, Саш! :)

Share this post


Link to post
Share on other sites

Итак, найдено решение, позволяющее нам отказаться от PHP.

Оказалось всё достаточно просто.

Теперь наш .htaccess имеет вид

<IfModule mod_headers.c>

	Header set Cache-Control "max-age=29030400, public"

</IfModule>

<IfModule mod_expires.c>

	ExpiresActive On

	ExpiresDefault A29030400

</IfModule>


AddEncoding x-gzip .gz

AddType text/css .gz


RewriteEngine on

# Вырезаем версию

RewriteRule ^(.*\.)v[0-9\.]+\.css$	$1css


RewriteCond %{HTTP:Accept-Encoding} gzip [OR]

RewriteCond %{HTTP:TE} gzip

RewriteCond %{HTTP_USER_AGENT} !Safari

RewriteCond %{HTTP_USER_AGENT} !Konqueror

RewriteCond %{REQUEST_FILENAME}.gz -f

RewriteRule ^(.*)\.css$	$1.css.gz

файл index.php из папки css удаляем - он нам больше не нужен :)

Edited by Александр Медведев

Share this post


Link to post
Share on other sites

Да, идея хорошая и даже работает.

Только для параноиков хочется сообщать, что в этом случае валидатор CSS (jigsaw.w3.org) будет плеваться, так как сообщит об отсутствии файла style.v1.0.css

Share this post


Link to post
Share on other sites

алидатор CSS (jigsaw.w3.org) будет плеваться, так как сообщит об отсутствии файла style.v1.0.css
не согласен, валидатор точно так же как и браузер обратится по адресу "css/style.v1.0.css", а апач незаметненько подменит адрес на реальный "css/style.css" и все будут думать, что всё ок :)

На этом и основана работа mod_rewrite

Share this post


Link to post
Share on other sites

провел эксперимент... все так же, как описано выше.

Sorry! We found the following errors (1)

URI : http://ateks.com.ua/css/ateks.v1.0.css

-1 File not found: http://ateks.com.ua/css/ateks.v1.0.css: Not Found

не сочтите за рекламу - исключительно для наглядности.

Share this post


Link to post
Share on other sites

ну да, странно.

Но я думаю ничего страшного в этом нет

Share this post


Link to post
Share on other sites

Оно то да, ничего страшного, но вот некоторые, особо придирчивые заказчики. большинству все равно как верстается, по стандартам или "что бы работало", а вот некоторые спрашивают.

Подозреваю, что этот самый валидатор как то непонятно проверяет, не объявляя себя. Файл .htaccess обрабатывает клиентский браузер, а валидатор, похоже, на него просто не обращает внимания.

Ну да ладно, это такое дело.

Еще раз спасибо за хорошую идею.

Share this post


Link to post
Share on other sites

Спасибо большое! многому учусь по твоим статьям и ответам на вопросы. :)

Share this post


Link to post
Share on other sites

а как запретить также в Google Chrome?а то не работает там gzip.

Share this post


Link to post
Share on other sites

win2008, это в какой версии? У меня в 2.0.172.30 работает

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...