¿Cómo puedo precomprimir archivos con mod_deflate en Apache 2.x?
-
09-06-2019 - |
Pregunta
Estoy sirviendo todo el contenido a través de Apache con Content-Encoding: zip
pero eso se comprime sobre la marcha.Una buena cantidad de mi contenido son archivos estáticos en el disco.Quiero comprimir los archivos de antemano en lugar de comprimirlos cada vez que se solicitan.
Esto es algo que, creo, mod_gzip
lo hizo en Apache 1.x automáticamente, pero solo tenía el archivo con .gz al lado.Ese ya no es el caso con mod_deflate
.
Solución
De todos modos, esta funcionalidad estaba fuera de lugar en mod_gzip.En Apache 2.x, eso lo haces con la negociación de contenidos.Específicamente, debe habilitar MultiViews
con el Options
directiva y debe especificar sus tipos de codificación con el AddEncoding
directiva.
Otros consejos
Para responder a mi propia pregunta con la línea realmente simple que me faltaba en mi configuración:
Options FollowSymLinks MultiViews
Me faltaba la opción MultiViews.Está ahí en la configuración del servidor web predeterminado de Ubuntu, así que no seas como yo y lo dejes.
También escribí una tarea rápida de Rake para comprimir todos los archivos.
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
Me temo que MultiViews no funcionará como se esperaba:el documento dice que Multiviews funciona "si el servidor recibe una solicitud de /some/dir/foo, si /some/dir tiene MultiViews habilitado y /some/dir/foo no existe...", en otras palabras:Si tiene un archivo foo.js y foo.js.gz en el mismo directorio, simplemente activar MultiViews no hará que se envíe el archivo .gz incluso si el navegador transmite el encabezado gzip AcceptEncoding (puede verificar este comportamiento haciendo clic en deshabilitar temporalmente mod_deflate y monitorear la respuesta con, por ejemplo,HTTPFox).
No estoy seguro de si hay una manera de solucionar esto con MultiViews (tal vez pueda cambiar el nombre del archivo original y luego agregar una directiva AddEncoding especial), pero creo que puede construir una regla mod_rewrite para manejar esto.
Tengo un Apache 2 creado desde el código fuente y descubrí que tenía que modificar lo siguiente en mi httpd.conf archivo:
Agregar vistas múltiples a las opciones:
Options Indexes FollowSymLinks MultiViews
Descomentar AddEncoding:
AddEncoding x-compress .Z AddEncoding x-gzip .gz .tgz
Comentario Agregar tipo:
#AddType application/x-compress .Z #AddType application/x-gzip .gz .tgz
Es posible servir archivos precomprimidos usando mod_negotiation
aunque es un poco quisquilloso.La principal dificultad es que sólo se negocian solicitudes de archivos que no existen.Así que si foo.js
y foo.js.gz
ambos existen, respuestas para /foo.js
siempre estará descomprimido (aunque las respuestas para /foo
funcionaría correctamente).
La solución más fácil que he encontrado (de François Marier) es cambiar el nombre de los archivos sin comprimir con una extensión de archivo doble, por lo que foo.js
se despliega como foo.js.js
entonces las solicitudes de /foo.js
negociar entre foo.js.js
(sin codificación) y foo.js.gz
(codificación gzip).
Combino ese truco con la siguiente configuración:
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>
I escribió una publicación que analiza en detalle el razonamiento de esta configuración y algunas alternativas.
mod_gzip también comprime el contenido sobre la marcha.Puede precomprimir los archivos iniciando sesión en su servidor y haciéndolo desde el shell.
cd /var/www/.../data/
for file in *; do
gzip -c $file > $file.gz;
done;
Puedes usar mod_cache
para proxy de contenido local en la memoria o en el disco.No sé si esto funcionará como se esperaba con mod_deflate
.
Tengo muchos archivos .json grandes.La mayoría de los lectores se encuentran en esta situación.Las respuestas de vista previa no hablaban sobre el "tipo de contenido" devuelto.
Si desea que la siguiente solicitud devuelva un archivo precomprimido con "Tipo de contenido:application/json" de forma transparente, use Multiview con ForceType
http://www.domain.com/(...)/bigfile.json
-> Content-Encoding:gzip, Content-Type: Content-Encoding:gzip
1) se debe cambiar el nombre de los archivos:"archivo.ext.ext"
2) Multiview funciona muy bien con ForceType
En el sistema de archivos:
// Note there is no bigfile.json
(...)/bigfile.json.gz
(...)/bigfile.json.json
En tu configuración de Apache:
<Directory (...)>
AddEncoding gzip .gz
Options +Multiviews
<Files *.json.gz>
ForceType application/json
</Files>
</Directory>
Corto y sencillo :)