Как разместить статический контент, предварительно сжатый в apache?

Я размещаю игру на JavaScript, которая в основном состоит из файлов.html и.data. Если я сожму их с помощью gzip, их размер уменьшится до 25%. Поэтому я хочу сделать это.

Я не уверен на 100%, но я думаю, что использование mod_gzip или mod_deflate делает сжатие на лету, тратя время процессора все время, потому что содержимое не меняется.

Поэтому я хотел бы предварительно скомпилировать Контент. Поэтому я помещаю.gz рядом с несжатыми файлами и помещаю правила перезаписи в.htaccess:

RewriteEngine on 
# If client accepts compressed files 
RewriteCond %{HTTP:Accept-Encoding} gzip 
# and if compressed file exists 
RewriteCond %{REQUEST_FILENAME}.gz -f 
# send .html.gz instead of .html 
RewriteRule ^(.+)\.(html|css|js|data)$ $1.$2.gz [T=text/$2,E=GZIP:gzip,L] 
Header set Content-Encoding gzip env=GZIP 

Перенаправление работает, я могу запросить game.html и получить доставленный game.html.gz. Тем не менее, браузер не просто отображает его. Вместо этого он спрашивает меня, где сохранить файл. Как я могу это исправить? Или, может быть, есть другой способ достичь моей цели?

5 ответов

Решение

Вот как я однажды исправил ту же проблему.

Добавьте новые типы в.htaccess:

AddEncoding gzip .jsgz .cssgz .htmlgz .datagz
AddType application/javascript .jsgz
AddType text/css .cssgz
AddType text/html .htmlgz       
AddType text/plain .datagz

Это было сделано так, потому что AddType Инструкция не принимает расширения в форме.html.gz.

Затем измените правило перезаписи:

RewriteRule ^(.+)\.(html|css|js|data)$ $1.$2gz [L] 

И наконец переименуйте ваши файлы. Удалите точки из.html.gz, .js.gz и так далее.

Полный.htaccess будет выглядеть так:

AddEncoding gzip .jsgz .cssgz .htmlgz .datagz
AddType application/x-javascript .jsgz
AddType text/css .cssgz
AddType text/html .htmlgz       
AddType text/plain .datagz

RewriteEngine on 
# If client accepts compressed files 
RewriteCond %{HTTP:Accept-Encoding} gzip 
# and if compressed file exists 
RewriteCond %{REQUEST_FILENAME}gz -f 
# send .html.gz instead of .html 
RewriteRule ^(.+)\.(html|css|js|data)$ $1.$2gz [L] 

Первый вопрос, который вы должны задать себе: есть ли смысл делать это? Заметили ли вы слишком высокую загрузку процессора и / или разницу в производительности из-за этого? Я думаю, что вы, вероятно, не столкнулись с этой проблемой:)

Несмотря на это, существует несколько способов решения вашей проблемы.

  1. Вероятно, лучший вариант для вас, используйте CDN. Они предназначены для быстрой доставки статических файлов и ускорят их как для людей в другом географическом регионе, так и для людей, находящихся рядом с вашим сервером. Кроме того, по моему опыту CDN обычно намного дешевле, чем ваша собственная пропускная способность.

  2. Используйте Nginx. Хостинг статических файлов намного быстрее и поддерживает предварительную генерацию статического контента, как вы делаете сейчас. Он автоматически обнаружит, есть ли .gz подайте и подайте это вместо этого когда необходимо.

  3. Используйте один из механизмов кэширования Apache, например mod_mem_cache или же mod_disk_cache чтобы убедиться, что каждый регулярно используемый файл будет в кеше. Учебное пособие: http://webdirect.no/linux/apache-caching-with-gzip-enabled/

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

Однако для вашей текущей версии что-то вроде этого (непроверенное) должно помочь:

RewriteEngine On    
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.*)\.(html|css|js|data) $1\.$2\.gz [QSA]

# Prevent double gzip and give the correct mime-type
RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1,E=FORCE_GZIP]
RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1,E=FORCE_GZIP]
RewriteRule \.html\.gz$ - [T=text/html,E=no-gzip:1,E=FORCE_GZIP]
RewriteRule \.data\.gz$ - [T=text/plain,E=no-gzip:1,E=FORCE_GZIP]

Header set Content-Encoding gzip env=FORCE_GZIP

Принятый ответ кажется довольно болезненным. Ответ Вольфа кажется лучше, но все же требуется отдельная конфигурация для каждого расширения файла и отсутствует поддержка более сложных согласований ( q-значения, статус 406, TCN и т. Д.). Вместо того, чтобы самостоятельно выполнять согласование содержимого mod_rewriteвы можете рассмотреть возможность использования mod_negotiation как обсуждалось в этом вопросе. Копирую мой ответ оттуда:

Options +MultiViews
RemoveType .gz
AddEncoding gzip .gz
<FilesMatch ".+\.tar\.gz$">
    RemoveEncoding .gz
    # Note:  Can use application/x-gzip for backwards-compatibility
    AddType application/gzip .gz
</FilesMatch>

Это имеет дополнительный бонус работы для всех .gz файлы, а не только явно настроенные и легко расширяемые для brotli или других кодировок.

Он имеет один существенный недостаток, так как только запросы на файлы, которые не существуют, согласовываются с файлом с именем foo.js будет делать запросы на /foo.js (но нет /foo) вернуть несжатую версию. Этого можно избежать, используя решение Франсуа Мариера о переименовании несжатых файлов с двойным расширением, поэтому foo.js развернут как foo.js.js,

Как насчет решения, изложенного здесь: http://feeding.cloud.geek.nz/posts/serving-pre-compressed-files-using/. Используйте встроенные в Apache MultiViews...

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

Это выглядитREQUEST_FILENAMEв зависимости от контекста и места, где вы переписываете код, определяет, получите ли вы полный путь к файловой системе или копию .

REQUEST_FILENAME
Полный путь в локальной файловой системе к файлу или сценарию, соответствующему запросу, если он уже определен сервером на момент обращения к REQUEST_FILENAME. В противном случае, например, при использовании в контексте виртуального хоста, то же значение, что и REQUEST_URI. В зависимости от значения AcceptPathInfo сервер мог использовать только некоторые ведущие компоненты REQUEST_URI для сопоставления запроса с файлом.

Ссылка: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html .

Чтобы исправить это, я обнаружил, что есть 2 возможных варианта.

Один из них — использовать модификатор прогнозирования согласно документации.

При использовании в контексте каждого сервера (т. е. до того, как запрос будет сопоставлен с файловой системой), SCRIPT_FILENAME и REQUEST_FILENAME не могут содержать полный путь к локальной файловой системе, поскольку на этом этапе обработки путь неизвестен. В этом случае обе переменные изначально будут содержать значение REQUEST_URI. Чтобы получить полный путь к локальной файловой системе запроса в контексте каждого сервера, используйте упреждающий просмотр %{LA-U:REQUEST_FILENAME} на основе URL-адреса, чтобы определить окончательное значение REQUEST_FILENAME.

Другой вариант, который не зависит от контекста или прогнозирования, как я обнаружил, заключается в использованииDOCUMENT_ROOTсREQUEST_URI.

Итак, если сложить все это вместе, это выглядит примерно так.

      
# ==============================================================================
# Serving pre-compressed content
# ==============================================================================
# Include in a vhost to enable Serving Gzip Files
# ------------------------------------------------------------------------------
# Ref:
# - https://httpd.apache.org/docs/2.4/mod/mod_deflate.html#precompressed
#

<IfModule mod_headers.c>
    <IfModule mod_rewrite.c>
        RewriteEngine On

        # Serve gzip compressed CSS and JS files if they exist
        # and the client accepts gzip.
        RewriteCond "%{HTTP:Accept-encoding}" "gzip"

        # REQUEST_FILENAME is only available as a full path once the requests
        # has been resolved so we need to use a look ahead or
        # DOCUMENT_ROOT+REQUEST_URI
        # RewriteCond "%{LA-U:REQUEST_FILENAME}\.gz"    "-s"
        RewriteCond "%{DOCUMENT_ROOT}%{REQUEST_URI}.gz" "-s"

        # Rewrite to gzip file
        RewriteRule "^(.*)\.(css|js)"                   "$1\.js\.gz" [QSA]

        # Serve correct content types, and prevent mod_deflate double gzip.
        RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
        RewriteRule "\.js\.gz$"  "-" [T=text/javascript,E=no-gzip:1]

        <FilesMatch "(\.js|\.css)$">
            Header append Pre-Compressed 0
        </FilesMatch>

        <FilesMatch "(\.js\.gz|\.css\.gz)$">
            # Serve correct encoding type.
            Header append Content-Encoding gzip

            # Force proxies to cache gzipped &
            # non-gzipped css/js files separately.
            Header append Vary Accept-Encoding
            Header append Pre-Compressed 1
        </FilesMatch>
    </IfModule>
</IfModule>

Было бы неплохо, если бы официальная документация Apache действительно указала на это или использовала один из этих двух примеров, которые работают во всех контекстах, поскольку за эти годы это, вероятно, сбило с толку многих людей.

Ссылка: https://httpd.apache.org/docs/2.4/mod/mod_deflate.html#precompressed .

Другие вопросы по тегам