Pergunta

I host a JavaScript game which basically consists of an .html and a .data file. If I compress them with gzip, their size shrinks to 25%. So I want to do that.

I'm not 100% sure, but I think using mod_gzip or mod_deflate does the compression on-the-fly, wasting cpu time all the time because the Content doesn't Change.

So I'ld like to precompile the Content. Therefore, I put a .gz next to the uncompressed files and put rewrite rules in .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 

The Redirect is working, I can request game.html and actually get deliviered game.html.gz. However, the browser doesn't just display it. Instead, it asks me where to save the file. How can I fix that? Or maybe there is another way to achieve my Goal?

Foi útil?

Solução

This is how i fixed once the same problem.

Add new types in .htaccess:

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

This was done this way because AddType instruction didn't accept extensions in the form .html.gz.

Then modify your rewrite rule:

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

And finally rename your files. Remove dots from .html.gz, .js.gz and so on.

The full .htaccess would look like this:

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] 

Outras dicas

The first question you should ask yourself is, is there any point in doing this? Do you notice too high cpu load and/or performance difference because of this? My guess would be that you are probably not running into this problem :)

Regardless though, there are multiple ways of fixing your problem.

  1. Probably the best option for you, use a CDN. They are designed for fast delivery of static files and will make it fast for people in a different geographical area as well as people close to your server. Also, in my experience CDN's are usually much cheaper than your own bandwidth will be.

  2. Use Nginx. For hosting static files much faster and has support for pre generating static content like you are doing right now. It will automatically detect if there's a .gz file and serve that instead when needed.

  3. Use one of the Apache cache mechanisms like mod_mem_cache or mod_disk_cache to make sure that every regularly used file will be in cache. Tutorial: http://webdirect.no/linux/apache-caching-with-gzip-enabled/

  4. Use a caching proxy like Varnish in front of it, these type of servers have a much smarter caching mechanism and will actually cache the files that matter most.

For your current version however, something like this (untested) should do the trick:

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

The accepted answer seems quite painful. Wolph's answer seems better, but still requires separate configuration for each file extension and lacks support for more advanced negotiation (q-values, status 406, TCN, etc.). Rather than implementing content negotiation yourself using mod_rewrite, you may want to consider using mod_negotiation as discussed in this question. Copying my answer from there:

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 has the added bonus of working for all .gz files rather than only explicitly-configured ones and being easily extended for brotli or other encodings.

It does have one major drawback, since only requests for files which do not exist are negotiated a file named foo.js would make requests for /foo.js (but not /foo) return the uncompressed version. This can be avoided using François Marier's solution of renaming uncompressed files with a double extension, so foo.js is deployed as foo.js.js.

What about the solution outlined here: http://feeding.cloud.geek.nz/posts/serving-pre-compressed-files-using/. Use Apache's built-in MultiViews...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top