Neil has brought this blog entry to my attention: http://www.fiftyfoureleven.com/sandbox/weblog/2004/jun/the-definitive-cs...
I looked at my css files and found that they sum up to 20 kB. Since it is all text it will compress nicely. Again, as with the gzipping of the page cache, so gain will be twofold: less bandwidth use (but we could mod_gzip for this) and less CPU cycles used for compressing the css on every transmission again.
I think that we should introduce a css hook where modules can add css files they want to add permanently. Currently the only way to to so is to abuse the _menu hook (see event.module for a correct example). This hook could then handle the gzipping and storage of the css files.
Comments
Comment #1
moshe weitzman commentedthe browser already caches external css files (along with other external files like javascript, images, etc.). thus, there is little benefit to zipping them. if you have the capability to gzip, then it makes sense to gzip all text files where the browser supports it.
Comment #2
killes@www.drop.org commentedI of course know that the css is cached by the browser and that other means are available for gzipping text files. The advantage of this solution is that the css is already gzipped inside the database so it does not need to be gzipped again for each new user. This will be particularly interesting when your site comes under a /. attack: A lot of new visitors who will all need your css and yet at the same time the server is already stressed with sefing pages. It would be convenient to save a few CPU cycles in this scenario. I admit that this is a fringe case and that this task isn't particularly high on my agenda.
Comment #3
bertboerland commentedmy first reaction was indeed that the webserver ought to do the gzipping. however, your point that this will only use more cycles when under /. is true. gzipping this static content so every user will get the same page (provided they use the same theme) looks like a good thing.
Comment #4
kbahey commentedI would like to revive this issue.
The two css files for pushbutton (I mean misc/drupal.css at 8% and theme/pushbutton/style.css at 12%) together make up for 20% of the bandwidth consumption.
Although it is true that css are cached, for sites that receive a lot of new traffic (not repeat visitors), this will be a problem. More so when you get Slashdotted as well!
I have resorted to a hack to reduce the size of the CSS files (remove all un-necessary white space, and newlines, as well as modules I do not use (e.g. aggregator, calendar, ...etc.). This reduces the file sizes by 25% for one file and 30% in the other. This should translate to 5% savings of the monthly bandwidth.
It seems a more proper solution is to implement what link that Killes pointed to in the original comment.
This, combined with PHP gzip compression for output, should cut down on bandwidth usage significantly.
Comment #5
(not verified) commentedActully, the *real* solutions lies in another direction IMO.
Drupal.css creates a lot of styles.
Yourstyle1.CSS overrides these again.
I recently did a complete non- drupal.css design, and reduced my complete stylesheet size with about 70%!
combined with sections module to allow the admin pages to still use drupal.css, but not send these administration styles to all the other users, I managed to reduce my CSS bandwith with up to 80%.
Unfortunately the code and themes are still too customised to share them.
Thats a lot IMO.
Bèr
Comment #6
killes@www.drop.org commentedThere are in principle two ways to deal with this issue:
1) store gzipped CSS files in the database.
2) store them on the hard disk
I tend to prefer 2).
The question is:
How do we redirect the browser to ask for the gzipped files instead if the original uncompressed ones?
Comment #7
Richard Archer commentedI've had a bit of a think about this and I'd like to throw out a plan for discussion.
First, the scope.
No matter how these files are stored they need to be served up by a script. This script needs to:
- check that the browser can handle gzipped data
- send the appropriate headers
- send the gzipped data to the browser
- manage cache expiry
- rebuild the cached gzipped data from the original files
The @import and src= statements needs to point to this script. Either all the code that outputs one of these statements needs to be modified or these statements need to be re-written on the fly. I think the best option is to re-write the statements in drupal_get_html_head. This would allow this feature to be controlled from one place should a "on/off" setting be required. The rewriting should be achieved by a fairly simple PCRE.
There are as I see it two options for the script that gets called.
The first is to create a new .php script that contains whatever code (or imports chunks of the drupal base code) to manage the caching etc. This would allow the caching code to be pretty streamlined.
The second option is to let index.php catch these requests. This would suggest that the caching mechanism might follow the same code path through Drupal as a page request. This would perhaps add some overhead to each request but probably require less code and be a more elegant solution. Or index.php could detect that this is a request for a cached file and fork off to a different code-path.
I'm not sure which of these two options would be best. Would someone with better knowledge of the relevant parts of Drupal care to offer an opinion?
Comment #8
kbahey commentedWhatever option we chose should have a way to turn this off at the admin's choice. This can be a hidden variable in $conf array in settings.php.
Comment #9
killes@www.drop.org commentedStats for drupal.org, July 2006: 26 GB of CSS served, 14% of total bandwidth.
Comment #10
Christoph C. Cemper commentedwow... +1 from me - I got 43k html and 40k css on http://www.marketingfan.com/ !!!
Comment #11
solipsist commentedI'm all for it too! It's a great idea, and would save transfer which is expensive as we all know.
Comment #12
magico commentedFollowing #1 and #5 there are two things to do:
1. reduce CSS files and split them to be smaller and better re-used (done on current HEAD)
2. configure correctly the webserver to compress pages (HTML, CSS, JS, etc) and choose the right options to optimize webserver performance.
Compressing this kind of data (to gain performance) is *not* a Drupal problem, but a webserver one. Why would we add more code (add more bugs) in Drupal to have a feature that will do another (or several) database hits?
Even if we go throught the "file cache" path, we would only "re-inventing the wheel" because who really needs to save copies of compressed pages wwould be the webserver and never Drupal.
@killes: those stats are for uncompressed CSS? Can you activate your webserver compression module and re-evaluate the stats within one month or two?
Comment #13
jacauc commentedI could never really say with 100% confidence that the compression is working on my server.
If you look at a web page analyzer on the web, and query your page, they almost always come back with different results at different times.
Comment #14
magico commentedNo need to re-invent the wheel. A webserver like Apache and lighttpd, compress static files and save them on a dedicated cache, also having mechanisms to detect and re-compress changed files.
Comment #15
moshe weitzman commentedFWIW, groups.drupal.org is now compressing its css, js, and HTML at the apache level and is working well.
Comment #16
gremlinc5 commentedJust my two cents:
not every host provides support for mod_gzip or mod_deflate.
Mine doesn't, at least. So I looked around for a solution and I found JSmart (farhadi.ir/jsmart.html). It's a tool that compress both js and css at site level using php gzip compression. It seems it's fast (it implements an internal cache for gzipped contents) and it's easy to setup.
It's not perfect (it tries to minimize both js and css with mixed results), but it's simple enough to be modified really easily: I disabled compression commenting out just one line of code.
And it needs just mod_rewrite: js and css requests are redirected to the php compressor.
Comment #17
gremlinc5 commentedI finally published a module based on JSmart called SmartCache.
It handles Expires headers, transparent gzipping of js and css files and updates the cache when a requested file has been modified.