Como posso pré-compactar arquivos com mod_deflate no Apache 2.x?
-
09-06-2019 - |
Pergunta
Estou servindo todo o conteúdo através do Apache com Content-Encoding: zip
mas isso comprime na hora.Uma boa parte do meu conteúdo são arquivos estáticos no disco.Quero compactar os arquivos com antecedência, em vez de compactá-los sempre que forem solicitados.
Isso é algo que, acredito, mod_gzip
fiz no Apache 1.x automaticamente, mas apenas tendo o arquivo com .gz próximo a ele.Isso não é mais o caso mod_deflate
.
Solução
De qualquer forma, esta funcionalidade foi perdida no mod_gzip.No Apache 2.x, você faz isso com negociação de conteúdo.Especificamente, você precisa ativar MultiViews
com o Options
diretiva e você precisa especificar seus tipos de codificação com o AddEncoding
diretiva.
Outras dicas
Para responder à minha própria pergunta com a linha realmente simples que faltava na minha configuração:
Options FollowSymLinks MultiViews
Estava faltando a opção MultiViews.Ele está na configuração padrão do servidor web do Ubuntu, então não seja como eu e deixe-o cair.
Também escrevi uma tarefa rápida do Rake para compactar todos os arquivos.
namespace :static do
desc "Gzip compress the static content so Apache doesn't need to do it on-the-fly."
task :compress do
puts "Gzipping js, html and css files."
Dir.glob("#{RAILS_ROOT}/public/**/*.{js,html,css}") do |file|
system "gzip -c -9 #{file} > #{file}.gz"
end
end
end
Receio que o MultiViews não funcione conforme o esperado:o documento diz que Multiviews funciona "se o servidor receber uma solicitação para /some/dir/foo, se /some/dir tiver MultiViews ativado e /some/dir/foo não existir...", em outras palavras:se você tiver um arquivo foo.js e foo.js.gz no mesmo diretório, apenas ativar MultiViews não fará com que o arquivo .gz seja enviado mesmo que o cabeçalho gzip AcceptEncoding seja transmitido pelo navegador (você pode verificar esse comportamento por desabilitando temporariamente mod_deflate e monitorando a resposta com, por exemplo.HTTPFox).
Não tenho certeza se existe uma maneira de contornar isso com MultiViews (talvez você possa renomear o arquivo original e adicionar uma diretiva AddEncoding especial), mas acredito que você pode construir uma regra mod_rewrite para lidar com isso.
Eu tenho um Apache 2 construído a partir do código-fonte e descobri que precisava modificar o seguinte em meu httpd.conf arquivo:
Adicione MultiViews às opções:
Options Indexes FollowSymLinks MultiViews
Remova o comentário AddEncoding:
AddEncoding x-compress .Z AddEncoding x-gzip .gz .tgz
Comentário AddType:
#AddType application/x-compress .Z #AddType application/x-gzip .gz .tgz
É possível servir arquivos pré-compactados usando mod_negotiation
embora seja um pouco meticuloso.A principal dificuldade é que apenas solicitações de arquivos que não existem são negociadas.Então se foo.js
e foo.js.gz
ambos existem, respostas para /foo.js
sempre será descompactado (embora as respostas para /foo
funcionaria corretamente).
A solução mais fácil que encontrei (de François Marier) é renomear arquivos descompactados com uma extensão de arquivo dupla, então foo.js
é implantado como foo.js.js
então pedidos de /foo.js
negociar entre foo.js.js
(sem codificação) e foo.js.gz
(codificação gzip).
Eu combino esse truque com a seguinte configuração:
Options +MultiViews
RemoveType .gz
AddEncoding gzip .gz
# Send .tar.gz without Content-Encoding: gzip
<FilesMatch ".+\.tar\.gz$">
RemoveEncoding .gz
# Note: Can use application/x-gzip for backwards-compatibility
AddType application/gzip .gz
</FilesMatch>
EU escreveu uma postagem que discute detalhadamente o raciocínio para esta configuração e algumas alternativas.
mod_gzip também comprimiu conteúdo dinamicamente.Você pode pré-compactar os arquivos fazendo login no servidor e fazendo isso a partir do shell.
cd /var/www/.../data/
for file in *; do
gzip -c $file > $file.gz;
done;
Você pode usar mod_cache
para proxy de conteúdo local na memória ou no disco.Não sei se isso funcionará como esperado com mod_deflate
.
Eu tenho muitos arquivos .json grandes.A maioria dos leitores está nesta situação.As respostas de visualização não falaram sobre o "tipo de conteúdo" retornado.
Se você quiser que a seguinte solicitação retorne um arquivo pré-compactado com "Content-Type:application/json" de forma transparente, use Multiview com ForceType
http://www.domain.com/(...)/bigfile.json
-> Content-Encoding:gzip, Content-Type: Content-Encoding:gzip
1) os arquivos devem ser renomeados:"arquivo.ext.ext"
2) Multiview funciona muito bem com ForceType
No sistema de arquivos:
// Note there is no bigfile.json
(...)/bigfile.json.gz
(...)/bigfile.json.json
Na configuração do seu apache:
<Directory (...)>
AddEncoding gzip .gz
Options +Multiviews
<Files *.json.gz>
ForceType application/json
</Files>
</Directory>
Curto e simples :)