Assets JSmin / CSSmin + Gzip

Currently the used JS is put in a generated assets directory. Currently most of it is 'bare' and uncompressed Javascript.

There might be some options to auto-compress these files and even combine it in one. To enable long-term usercache and send the file(s) Gzipped, it can be an option to make the files PHP. Currently I gather all JS, JSmin it, and save it. I give the file a .php extension and include the following line on top of it:

<?php 


header("Content-type: text/javascript; charset: UTF-8"); 


$headers = apache_request_headers();


if (isset($headers["If-Modified-Since"]) && (strtotime($headers["If-Modified-Since"]) == 1226100514)) {


	header("Cache-Control: must-revalidate");


	header("Last-Modified: Fri, 07 Nov 2008 23:28:34 GMT", true, 304);


	exit();


} else {


	header("Last-Modified: Fri, 07 Nov 2008 23:28:34 GMT", true, 200);


	header("Cache-Control: must-revalidate");


	header("Expires: Tue, 29 Dec 2009 15:28:34 GMT");


}?>


(you should generate the dates of course) Same thing can be done for CSS files, and can save a bunch of HTTP requests (and a lot of data xfer).

CDN contradicts a bit with the above, but currently Google (and others) offers the possibility to use the jQuery CDN, potentially saving the transfer, and faster responses.

Yeah, this is something that wei and I had quite some discussion already.

So for 1.0 release, we will keep things simple, i.e., using the current scheme to send js/css. I am going to change CClientScript to make it an application component. This would allow us to customize the way client scripts are rendered.

We will have more enhancements along this line for 1.1 release. Thank you for your suggestion.

Would like to bump this feature  ;D, my YSlow grading is down to F now just bcz of all the JS and CSS files…

CClientScript is already an application component. That means, you can freely implement and plug in whatever compression or optimization techniques with CSS and JS. I will work on this for 1.1 release. Right now I am working on some more urgent features.

If you are running apache, try mod_deflate and mod_expires. Together they can provide very aggressive cache settings.

Yeah but for one reason or another is mod_deflate quite stubborn with my js files. Besides that it will not prevent the costly http-roundtrip for each file.

Mod_expires will help a lot after initial load for sure. Maybe a good idea to put together a nice .htaccess here? (Even better: put it in your httpd.conf.)

Currently mine:



Options +FollowSymLinks


IndexIgnore */*


RewriteEngine on





# If lang is in the first part


RewriteRule ^(es|en|nl)/?(.*)    index.php/$2?lang=$1 [NC,QSA,L]





# if a directory or a file exists, use it directly


#RewriteCond %{REQUEST_FILENAME} !-f


#RewriteCond %{REQUEST_FILENAME} !-d





RewriteCond %{REQUEST_URI} !^(/index.php|/assets|/images|/css|/w3c|/robots.txt|/favicon.ico)





# otherwise forward it to index.php


RewriteRule . index.php





<IfModule mod_deflate.c>


	AddOutputFilterByType DEFLATE text/xhtml text/html text/plain text/xml text/javascript application/x-javascript text/css


</IfModule>





<ifModule mod_expires.c>


  <filesmatch ".(ico|flv|jpg|jpeg|png|gif|js|css|swf)$">


       ExpiresActive on


       ExpiresDefault "access plus 1 year"


   </filesmatch>


</ifModule>





FileETag none


Adding etags in the header also helps with cache invalidation. The settings we use are along the lines of



# Insert filter


SetOutputFilter DEFLATE





# Don't compress images


SetEnvIfNoCase Request_URI 


.(?:gif|jpe?g|png)$ no-gzip dont-vary





# Don't compress binaries


SetEnvIfNoCase Request_URI  


.(?:exe|t?gz|zip|gz2|sit|rar)$ no-gzip dont-vary





# Make sure proxies don't deliver the wrong content


Header append Vary User-Agent env=!dont-vary





# aggressive cache settings by mime type, may bust cache by changing filenames


ExpiresByType text/css "access plus 10 years"


ExpiresByType text/javascript "access plus 10 years"


ExpiresByType application/x-javascript "access plus 10 years"


ExpiresByType image/gif "access plus 10 years"


ExpiresByType image/jpg "access plus 10 years"


ExpiresByType image/png "access plus 10 years"





<FilesMatch .(?i:gif|jpe?g|png|css|js)$>


    FileETag MTime Size


</FilesMatch>


YSlow punishes you when enabling ETags. This is probably true when you use multiple servers.

Thanks for sharing your use of deflate, will try that to see if my JS files will be Gzipped now.

Later versions of YSlow gives good grades to ETags that are not machine dependent. Such as using "FileETag MTime Size", that is, not including Inode (machine dependent).

Quote

Yeah but for one reason or another is mod_deflate quite stubborn with my js files. Besides that it will not prevent the costly http-roundtrip for each file.

I learned someday that there are bugs in some older versions of MSIE which prevented them to work correctly with gziped javascripts, too. But I think they were 5.5 or something like that.