如何在apache中托管预压缩的静态内容?

mar*_*000 20 javascript apache .htaccess mod-rewrite http-compression

我主持一个基本上由.html和.data文件组成的JavaScript游戏.如果我用gzip压缩它们,它们的大小会缩小到25%.所以我想这样做.

我不是百分百肯定,但我认为使用mod_gzip或mod_deflate即时进行压缩,因为内容不会改变,所以总是浪费cpu时间.

所以我想预先编译内容.因此,我将.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 
Run Code Online (Sandbox Code Playgroud)

重定向工作正常,我可以请求game.html并实际获得发送的game.html.gz. 但是,浏览器不会只显示它.相反,它会询问我保存文件的位置.我该如何解决这个问题?或者也许有另一种方法来实现我的目标?

cla*_*fob 18

这就是我一旦解决同样问题的方法.

在.htaccess中添加新类型:

AddEncoding gzip .jsgz .cssgz .htmlgz .datagz
AddType application/javascript .jsgz
AddType text/css .cssgz
AddType text/html .htmlgz       
AddType text/plain .datagz
Run Code Online (Sandbox Code Playgroud)

这是通过这种方式完成的,因为AddType指令不接受.html.gz形式的扩展.

然后修改重写规则:

RewriteRule ^(.+)\.(html|css|js|data)$ $1.$2gz [L] 
Run Code Online (Sandbox Code Playgroud)

最后重命名您的文件.从.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] 
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案真正适用于现场项目多年.如果AddType支持复杂的扩展名,例如.html.gz,则无法重命名文件. (2认同)

Wol*_*lph 10

你应该问自己的第一个问题是,这样做有什么意义吗?你是否注意到CPU负载和/或性能差异太大?我的猜测是你可能没有遇到这个问题:)

无论如何,有多种方法可以解决您的问题.

  1. 可能是您的最佳选择,请使用CDN.它们专为快速传送静态文件而设计,可以让不同地理区域的人以及服务器附近的人快速访问.另外,根据我的经验,CDN通常比你自己的带宽便宜得多.

  2. 使用Nginx.对于托管静态文件太多更快,有预就像你正在做的事情生成静态内容的支持.它会自动检测是否有.gz文件,并在需要时提供.

  3. 使用其中一个Apache缓存机制,mod_mem_cachemod_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
Run Code Online (Sandbox Code Playgroud)


Kev*_*oid 7

接受的答案似乎很痛苦. Wolph的答案似乎更好,但仍然需要为每个文件扩展名单独配置,并且缺乏对更高级协商(q值,状态406,TCN等)的支持.您可能需要考虑使用此问题中讨论的内容,而不是自己使用内容协商.从那里复制我的答案:mod_rewritemod_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>
Run Code Online (Sandbox Code Playgroud)

这为所有.gz文件工作提供了额外的好处,而不仅仅是明确配置的文件,并且可以轻松扩展为brotli或其他编码.

它确实有一个主要缺点,因为只有对不存在的文件的foo.js请求才会被协商,一个名为的文件会请求/foo.js(但不会/foo)返回未压缩的版本.这可以通过使用FrançoisMarier解决方案重命名具有双扩展名的未压缩文件来避免,因此foo.js部署为foo.js.js.