PDA

View Full Version : mod_gzip help. Unable to zip CSS and JS files



orion2001
05-26-2009, 01:50 AM
Hey everyone,

I'm a noob when it comes to Apache/.htaccess stuff. In any case, I have followed Falcon's excellent tutorial on enabling gzip compression on HM found here:
http://falcon1986.wordpress.com/2009/01/29/forcing-gzip-compression-on-your-hostmonster-hosted-website/

I am using php-single, with a php.ini file in my public_html folder. I have ensured that the following lines are present in my php.ini:

output_handler = ob_gzhandler
zlib.output_compression = Off
;zlib.output_handler =


In addition, I have added the following code to my .htaccess in public_html


<ifModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html|txt|css|js|php)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_include mime ^application/javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

Doing this has enabled gzip compression of text/html files which is confirmed by gzip test sites/http compression test sites. However none of my locally stored js and css files are being compressed. Looking at the .htaccess code, it seems like it should be compressing these files. Is this some limitation in the way mod_gzip is handled by HM servers (maybe some settings in httpd.conf)?

I'd really appreciate if any of the gurus here could help me out. My site uses prototype/scriptaculous and I'd really like to be able to compress the css and js files when my pages are served (I have a Wordpress Install).

If this method will not work for what I want, what method would you suggest so that I can enable css and js compression along with text/html compression?

Thanks a lot!

Cheers

orion2001
05-28-2009, 11:08 AM
After a number of back and forth emails with Tech Support (they were quite helpful although the initial responses seemed a little clueless) it turns out that both mod_deflate and mod_gzip are not enabled by HostMonster.

Thus it makes server side gzipping impossible, at least via using .htaccess

In addition, the inability to use php_value to auto_prepend a php file (for zipping via php) in front of files that match certain extensions is also not available.

What does seem to work is the compression of just the regular html files that are served. This is enabled if you use
output_handler = ob_gzhandler
in your php.ini or if you choose to instead enable zlib compression.

To enable js compression (which I really needed so as to compress the scriptaculous and prototype libraries), I had to invoke a manual method of gzipping the js files on my computer and uploading them in the same path as the original js file. Then by using Mod_Rewrite, it is possible to check if the browser accepts gzip encoding, and to then serve the .js.gz file (if it exists) or otherwise just serve the .js file. This works well, but means that I have to manually ensure that newer additions to the server are gzipped and up to date. Here is the .htaccess code I use (found on some websites comments)


<FilesMatch "\\.js.gz$">
ForceType text/javascript
Header set Content-Encoding: gzip
</FilesMatch>
<FilesMatch "\\.js$">
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} !".*Safari.*"
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule (.*)\.js$ $1\.js.gz [L]
ForceType text/javascript
</FilesMatch>

The one advantage of this method is that the server does not have to compress and generate these zip files every time they are requested. So you save bandwidth, lower your page load times and without any server side CPU penalty.

You can change this to also use this for CSS files. If anyone has gotten a better method to zip files and serve them, please do let me know. While this method works well, I really would wish that there was a way to serve gzipped files on the fly (so that I don't have to manually update all js gzip files when I install a new theme/plugins on my CMS)

rleeden
05-28-2009, 11:57 AM
orion2001 - thanks for posting an update. I'd been struggling with compressing JS and CSS too with my site on HostMonster.

Your solution, if not ideal, certainly seems to work. Thanks again.

orion2001
05-28-2009, 01:16 PM
rleeden,

I'm glad it helped you. Unfortunately there are a few older forum posts with people indicating that the DEFLATE command in .htaccess worked for them and that they were able to serve zipped files in that manner. Maybe mod_deflate was enabled in the past (along with possibly mod_gzip) but it is definitely disabled at the moment.

With regards to your css files, another method which I am currently employing is to create a master.css.php file which contains the following code:


<?php
header('Content-type: text/css');
$offset = 60*60*24; // Cache for a day
header ('Cache-Control: max-age=' . $offset . ', must-revalidate');
header ('Expires: ' . gmdate ("D, d M Y H:i:s", time() + $offset) . ' GMT');
ob_start("compress");
function compress($buffer) {
/* remove comments */
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
return $buffer;
}

/* Include all your css files */
include('http://www.yoursite.com/css/style.css');

ob_end_flush();
?>

Here you can include all the standard css files loaded by your site. The advantage is that

a) If you have multiple css files on your site, this will end up loading all of them under one http request...something that is good for site loading speeds

b) Since you reference the actual css file, even if it is updated (say from a plugin/theme upgrade), as long as the css file name/path remains the same it will work fine and serve the updated gzipped css files.

Disadvantages are:
a) Zip made on the fly via php every time
b) You have to go in manually and remove the calls for css files from your theme/plugin php since you are already loading via this master file. Then just call this file in your header with something like:


<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>.php" type="text/css" media="screen" />

Both methods have their advantages/disadvantages. Now that I think of it, it seems that the mod_rewrite method is probably still easier for css on the whole as you don't need to tweak anything in the theme/plugin files and it degrades to serving uncompressed stuff naturally. The problem there is that if you are tweaking your themes css a decent bit it can get tedious to constantly create new update gzip versions of your css files.

Falcon1986
05-28-2009, 03:40 PM
How are you determining whether the JS and CSS files are compressed?

I will have to recheck phpinfo() to see what compression methods are available.

BTW, have you given phpSpeedy and WP-Super Cache a try? So far, they seem to work just fine together on my WordPress installation. I let WP-Super Cache handle compression and caching, while phpSpeedy combines JS/CSS files and minifies them (no compression). I've been able to achieve a nice score of 96 using YSlow+Firebug.

Note that in implementing the above workarounds I have also deactivated server-side compression (reset my php.ini file and removed the mod_gzip statements from .htaccess). Allowing PHP to invoke compression should be fine for small websites; larger websites should get compression properly set up on the server.

orion2001
05-28-2009, 06:47 PM
Hey there Falcon,

Thanks for your reply. I have been checking on the compression using both YSlow+Firebug as well as this site: http://site-perf.com/
which I have found to be quite reliable in reporting compression, etc.

I actually did try WP- Super Cache, but for some reason (maybe the upgrade to WP 2.7.1), the Caching has been acting strange. It creates the gzip files within my cache folders but does not serve them, and instead serves the uncompressed cache files. I used all the htaccess settings that are recommended by the plugin author. Could you share your .htaccess settings that work well for you with Super Cache?

I am currently using a combo of HyperCache and DB-Cache, but the gzip serving in HyperCache also didn't seem to work for me.

As for PHP Speedy, I did give it a try but it didn't work for me. It seemed to create the compressed files in it's own cache, but it didn't seem to serve them. For example when I checked on the page source for my pages, they still references all my css and js files. Is PHP Speedy supposed to remove these calls made by the theme/plugins and replace it with the call for the minified js/css combo file?

I'd love to give this another shot as my current method is a bit of a pain. WP-Super Cache used to work well for me but off late with the newer versions it has seemed a little quirky. In any-case, all I really want is the ability to serve zipped css and js files to lower my site loading times.

Your current situation (combining/minifying js and css with PHP Speedy) seems ideal. I'd love to get that to work. If you could give me some pointers and some idea on how your htaccess is setup, that would be great.

Thanks.

Falcon1986
06-16-2009, 09:44 AM
First of all, sorry for not getting back to this sooner.

Recently, I decided to ditch WP-Super Cache and PHP Speedy and move over to more leaner methods of compression and caching. I'm also using DB-Cache and XCache, the latter of which I was successfully able to install after following instructions from a BlueHost (http://rk.md/2009/xcache-bluehost/) user. I then implemented the XCache Object Cache plugin for WordPress 2.5+ (http://dougal.gunters.org/blog/2008/08/29/xcache-object-cache-plugin-for-wordpress-25) and things seem to be a bit snappier. Anyway, I digress...

I am starting to agree with you as it concerns GZIP compression on HostMonster servers. However, I believe the only proper way to get it to work is probably as you described: invoke the use of PHP.

After compressing the WordPress theme's CSS, I created a style.css.php file with the following at the very top then specified the absolute path in header.php:


<?php
ob_start ("ob_gzhandler");
header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 ;
$ExpStr = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
header($ExpStr);
?>

The result, at least for the CSS is...

http://i34.photobucket.com/albums/d144/Falcon1986/gzip_compress1.png

Surprisingly, the hompage file itself is also being compressed, and note that I'm still using the same .htaccess edits you saw on my blog:


<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(js|css|html|php)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>

I'm still working on the Javascript compression at the moment. My theme calls for jQuery in the header and you probably know how large that can get. I will be revisiting WP-CSS (http://wordpress.org/extend/plugins/wp-css/) and WP-JS (http://wordpress.org/extend/plugins/wp-js/) to see if anything can be done from there.

As for caching I'm using something similar to what is stated here (http://webstandardsgroup.org/resource/792) for forcing client-side caching through .htaccess. May probably modify this later, but this method eliminates having to use any WordPress plugin.