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

时间:2013-06-02 13:32:18

标签: 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 

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

4 个答案:

答案 0 :(得分:18)

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

在.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 :(得分:9)

你应该问自己的第一个问题是,这样做有什么意义吗?你是否注意到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这样的缓存代理,这些类型的服务器具有更智能的缓存机制,并且实际上会缓存最重要的文件。

  5. 对于你当前的版本,这样的事情(未经测试)应该可以解决这个问题:

    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
    

答案 2 :(得分:6)

接受的答案似乎很痛苦。 Wolph's answer似乎更好,但仍然需要为每个文件扩展名单独配置,并且不支持更高级的协商(q-valuesstatus 406TCN等)。您可以考虑使用content negotiation中讨论的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> 自己实施this question。从那里复制my answer

.gz

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

它确实有一个主要缺点,因为 only requests for files which do not exist are negotiated 名为/foo.js的文件会请求/foo(但不是foo.js)返回未压缩的版本。使用François Marier's solution重命名具有双重扩展名的未压缩文件可以避免这种情况,因此foo.js.js部署为class Customer < ActiveRecord::Base has_many :jobs, dependent: :destroy end class Job < ActiveRecord::Base belongs_to :customer has_many :receipts, dependent: :destroy end class Receipt < ActiveRecord::Base belongs_to :job end

答案 3 :(得分:3)

此处列出的解决方案如何:http://feeding.cloud.geek.nz/posts/serving-pre-compressed-files-using/。使用Apache的内置MultiViews ......