Простая настройка .htaccess для production

    Иногда, когда сайты хостятся на shared-хостинге или работа идет только с Apache, нужно сделать максимальную оптимизацию работы сервера и сайта соответсвенно. В статье приводятся несколько настроек, которые позволят вашему сайту работать лучше.



    1. Кодировка


    Всегда указываем кодировку. По умолчанию лучше выбирать utf-8.
    AddDefaultCharset UTF-8
    


    2. Редирект на один домен


    Для SEO оптимизации, желательно, чтобы сайт был размещен только на одном домене. Если у вас несколько доменов ссылаются на один сайт, делаем редиректы на основной домен. Желательно, чтобы он начинался с www.

    Сделаем это используя код 301

    <IfModule mod_rewrite.c>
        Options +Followsymlinks
        RewriteEngine On
    
        RewriteCond %{HTTP_HOST} ^example\.com [OR]
        RewriteCond %{HTTP_HOST} ^example2\.com  [OR]
        RewriteCond %{HTTP_HOST} ^www\.example2\.com
        RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]    
    </IfModule>
    


    3. Кеширование статических ресурсов


    Большое время загрузки страницы отбирает загрузка статических ресурсов. Большинство из них никогда не меняются. Но броузер при каждом запросе проверяет не изменился ли ресурс на сервере. В ответе броузер получает код 304 — ресурс не изменился, и берет ресурс с кеша. То есть, даже если ресурс находится в кеше, броузер делает запрос. В общем это выливается в дополнительную нагрузку на сервер и в замедлении парсинга страницы.

    Избавимся от этого. Для этого поставим время проверки обновления ресурса на несколько лет вперед, и отключим проверку ETag

    <FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
    Header set Cache-Control "public"
    Header set Expires "Fri, 21 Dec 2012 20:00:00 GMT" #Until the end of the world
    FileETag None
    </FilesMatch>
    


    4. Сжатие текстовых файлов


    Текствые файлы можно передавать броузеру в сжатом виде. Укажем необходимые директивы для этого.
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    


    Выводы


    Эти настройки подойдут большинству сайтов, которые работают с Apache, оптимизировав работу сервера и скорость загрузки страниц.
    Поделиться публикацией

    Комментарии 49

      +13
      >Для SEO оптимизации, желательно, чтобы сайт был размещен только на одном домене. Если у вас несколько доменов ссылаются на один сайт, делаем редиректы на основной домен. Желательно, чтобы он начинался с www.
      Как раз таки для SEO оптимизации основной домен должен быть без www, а все остальные редиректиться на него. Так как домен www.domen.ru, является по сути доменом третьего уровня. А в некоторых зарубежных поисковых системах (да и вообще чисто эстетически) домен второго уровня имеет большее значение, чем с www (третьего уровня). Конечно здесь стоит учитывать какой домен вы раскручиваете (если вы закупали ссылки для SEO на domen.com, то стоит сделать редиректы с www на http. Если вы закупили ссылки на www, то редиректы должны быть как указаны в статье).
        +1
        Спорный вопрос, существует и такая точка зрения, как у вас. Но такие сайты как google, youtube, microsoft, facebook все-таки делают редирект на www. Кроме того, такой подход имеет еще некоторые преимущества. Поэтому я и советую www.
          +16
          Указанным вами сайтам как-то положить на SEO. WWW в начале — это дань традиции.
            +1
            Я ориентируюсь на best-practices. Всем хорошим сайтам все равно на SEO. И статья не о SEO, хотите, делайте без www. Я не против :)
              +6
              >SEO оптимизации
              А тавтология вас не смущает не смущает?
                +2
                Нет никакой тавтологии. Это оптимизация по второй производной. Оптимизация оптимизации. Метаоптимизация, если хотите. :)
                  +1
                  Угу, как «предсказание прогноза» например
                –2
                Ваши слова были бы правильными лет 5-8 назад. Чтобы о новом хорошем сайте кто-то узнал и он получил начальную аудиторию без seo сейчас не обойтись, так как выдача пестрит раскрученными гавносайтами, дорами и сателитами. И найти там хороший сайт, который только что открылся, невозможно. А одной публикации о нем на паре известных ресурсов недостаточно чтобы он стал супер популярным.
              +1
              Кроме того, такой подход имеет еще некоторые преимущества.
              звучит многообещающе, но как-то недосказанно.
                +5
                Речь идет о возможности ставить куки на www.domain.com.
                Которые не будут распространяться на static.domain.com.
                Это уже для тонкой оптимизации.

                См: Best Practices for Speeding Up Your Web Site, секция «Use Cookie-free Domains for Components»
                –1
                Согласен с DedalX по поводу www, начинаете сайт с 0 — лучше делать без www, если сайт уже работал через www и имеет всякие пузомерки, то лучше его и оставить на www.

                По поводу вообще настроек в htaccess то в проекте Kickstrap (который не так давно упоминался на харбе habrahabr.ru/post/141115/) есть очень хорошие настройки с описанием что и почему. Скачайте посмотрите — не пожалеете.
                  0
                  Спасибо, посмотрю
                +16
                чего только не выдумают сео-оптимизаторы, чтоб показать, что они не зря едят свой хлеб
                0
                Спасибо за то, что поделились!

                Интересует вопрос немного не по теме: почему желательно, чтобы основной домен начинался с www? Каким образом это влияет на SEO?
                0
                Ещё бы флажок QSA добавить в редирект
                  0
                  Мне кажется, это не существенно в этом месте.

                  Если в приложении вы используете скрипт с паттерном «Фронт контроллер», то эти флаги нужны именно там.

                  <IfModule mod_rewrite.c>
                      RewriteEngine On
                      RewriteCond %{REQUEST_FILENAME} !-d
                      RewriteCond %{REQUEST_FILENAME} !-f
                      RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
                  </IfModule>
                  
                    +1
                    При чём тут вообще фронт контроллер.

                    Если по каким-то причинам запрос пришёл на не тот домен, то без флажка QSA вы потеряете весь GET
                      0
                      Никогда не замечал, чтобы терялось.
                      Проверил, все ок.
                        0
                        Эм, с помощью какой магии в правиле

                        > RewriteRule ^(.*)$ www.example.com/$1 [R=301,L]

                        будет добавляться GET?

                        Вы уверены, что вы поняли проблему?
                          0
                          Проблему понял :)

                          Видимо QSA нет потому, что GET запросы не сливаются.

                          По идее если бы было RewriteRule ^(.*)$ www.example.com/?$1 [R=301,L], тогда точно нужно было.

                          Проверьте, все работает.
                            0
                            Гхм, и вправду. Неужели из-за R он query-string добавляет автоматом в этом случае :-S
                              0
                              А потом пхпешников обвиняют в низкой квалификации — чего гадать, если есть документация:
                              httpd.apache.org/docs/current/mod/mod_rewrite.html

                              Modifying the Query String

                              By default, the query string is passed through unchanged. You can, however, create URLs in the substitution string containing a query string part. Simply use a question mark inside the substitution string to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.

                              Qsa надо использовать если вы рерайтите не только путь, но и строку запроса, чтобы апач корректно скомбинировал старые и новые параметры.

                              Если вы не рерайтите строку запроса, то он просто передаст параметры без изменений
                                0
                                Никто и не гадал.

                                Спасибо за шпильку, без неё уж никак, конечно.

                                ps: а потом оказывается, что русские коммунити в основном состоят из комментариев с обкидыванием друг друга говном.
                                  –1
                                  Ну это давно известно, что русским только дай что-нибудь обгадить :-)

                                  Просто у вас довольно продолжительное получилось обсуждение параметра QSA, при этом ни та ни другая сторона обсуждения не пыталась даже обратиться к документации, хотя судя по сообщениям krugvs — он каким-то эмпирическим путем пришел к верному ответу, что qsa надо использовать когда происходит слияние запросов.
                                    0
                                    Я бы не стал судить, какой из ответов «верный» :-)

                                    Добавленный QSA хуже не сделает. Я его по инерции использую везде, где мне нужны параметры. И этот вариант явно не хуже, просто потому, что в случае модификации правила (добавления? с параметрами) ничего не сломается, а в сценарии с «указываем там, и только там, где нужно» — мы должны об этом помнить всегда.
                    +1
                    Bolerplate рекомендует без www и без QSA

                    # www.example.com должен направлять пользователей на example.com.
                    #   no-www.org/faq.php?q=class_b
                    <IfModule mod_rewrite.c>
                      RewriteEngine On
                      RewriteCond %{HTTPS} !=on
                      RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
                      RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
                    </IfModule>
                    

                    +3
                    2. Редирект на один домен
                    Зачем перечислять все домены, когда можно сделать так:
                    RewriteEngine on
                    RewriteCond %{HTTP_HOST} !^example\.org
                    RewriteRule ^(.*)$ http://example.org/$1 [R=permanent,L]
                    
                      +8
                      Потому что ещё могут быть домены, с которых не надо редиректить?
                      +5
                      Прокеширование у вас все неверно.
                      И с таким Expire он действительно наступит 21 декабря :)
                        +5
                        Пункт 4 можно записать и одной строчкой, просто перечислив типы
                        Для mod_expires можно еще так прописать настройки:

                        <ifModule mod_expires.c>
                          ExpiresActive On
                          ExpiresDefault "access plus 1 seconds"
                          ExpiresByType text/html "access plus 1 seconds"
                          ExpiresByType image/x-icon "access plus 2592000 seconds"
                          ExpiresByType image/gif "access plus 2592000 seconds"
                          ExpiresByType image/jpeg "access plus 2592000 seconds"
                          ExpiresByType image/png "access plus 2592000 seconds"
                          ExpiresByType text/css "access plus 604800 seconds"
                          ExpiresByType text/javascript "access plus 216000 seconds"
                          ExpiresByType application/x-javascript "access plus 216000 seconds"
                        </ifModule>
                        
                          0
                          Да, в основном пишут одной строчкой, для статьи формат с новых строк понятнее.
                          +4
                          А разве не надо все правила переносить в конфигурацию и убирать .htaccess на продакшене? Или я что-то забыл про апач?
                            +1
                            Все это и многое другое описано в HTML5 Boilerplate
                              0
                              А можно подобный пример для IIS?
                                0
                                Наверное есть что-то подобное для IIS, но я в основном работаю на LAMP.
                                –1
                                > Всегда указываем кодировку. По умолчанию лучше выбирать utf-8.
                                Этого не нужно делать НИКОГДА. Эта кодировка отдается в http заголовках и более приоритетна для браузера, нежели указанная внутри страницы в meta-теге с http-equiv=«Content-type». Не раз встречался с такими необычными хостингами, где приходилось дополнительно оверрайдить заголовок.
                                  0
                                  Ставьте ту же кодировку, что и в http-equiv=«Content-type».
                                    +1
                                    В некоторых случаях сервер (например, апач) перекодирует содержимое в кодировку, больше подходящую пользователю с точки зрения сервера. Если при этом указать кодировку в самой странице, она может не совпадать с той, в которой сервер отдаёт содержимое сайта. Поэтому тэг <meta> с указанием кодировки — не нужен.
                                      +1
                                      В некоторых случаях сервер (например, апач) перекодирует содержимое

                                      Едва ли он станет это делать по собственной инициативе. ;)
                                      А хостерам, которые используют подобные модули, надо вообще руки отрывать.
                                  +1
                                  Вот мне всегда было интересно: сжатие текстовых файлов происходит действительно налету?
                                  То есть компрессор работает «с нуля» при каждом запросе? Или какое-то кэширование есть?
                                    0
                                    В данном случае на лету. Кеширование уже будет отрабатывать на клиентской стороне. Сервер выполняет сжатие при каждом ответе
                                    +2
                                    Разве не практичнее использовать NGINX?
                                      0
                                      Втупил, речь ведь о shared…
                                        +2
                                        Если шаред хороший, nginx там уже стоит
                                          0
                                          как фронтэнд?
                                          А толку? всё равно не nginx+php-fpm)
                                            +1
                                            Ставят повсеместно, наверное толк есть
                                      0
                                      еще можно добавить выставлене MIME-типов, а DEFLATE можно в одну строку записать
                                        +2
                                        Не холивара ради, но в последнее время полностью перешёл на nginx и забыл об апаче. Может то же самое про nginx расскажете?

                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                        Самое читаемое