I ended up tweaking my copy so that it just built the dynamically created css in-page versus a menu'ed callback to a function that fakes a css page via content type header. I know it makes the source html on the page a little fatter, but here's the problem I was getting with the menu'ed callback: multiple page rendering.
For whatever reason, Drupal was building both css pages (screen/print) AS a Drupal entity inside of the pages that called it. So, I'd see "sifr print css" and "sifr screen css" statistics in my Drupal logs, one call each for *every* node viewed or otherwise accessed in my setup. In one day, those two became my "most popular" pages.
What's more, I was having difficulty with another one of my modules. The arg function, $_SERVER['QUERY_STRING'], $_GET['q'] AND the request_uri function were all returning the same wrong data....instead of saying that my querystring value was "node/123/edit" I was seeing node/123/sifr/print/css instead. I could only actually "see" this happening in a hook_exit function, other functions depending upon the querystring were just failing without explanation...I can only guess that this was part of the same issue. When I cached the querystring data to a session variable, I could see both print and screen css taking their turns as the subject of "q" as the same function was called three times in all before the page displayed. However, dynamically writing the text straight into the drupal_set_html_head function inside sifr_all_pages seems to have fixed all these issues while still allowing for flexible css generation.
I just thought I'd share. Maybe someone else wants to test to make sure it's not just me. I've tested this all on two totally different installations, and it seems to be a real thing. I can only imagine that these issues would have an adverse affect on resources (one page for the price of three), so maybe just shooting the css to drupal_set_html_head isn't a totally bad thing.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | sifr.patch | 6.94 KB | urbanfalcon |
Comments
Comment #1
jjeff commentedNow that you mention it, this does kind of make sense. I've recently found out that Drupal tells browsers NOT to cache the pages that it generates. This means that rather than caching CSS files like browsers usually would, they'll call them with EVERY page hit.
Good catch! I'll try and come up with a workaround for this.
Comment #2
jjeff commentedI need to look at the code again, but I think that the reason that I created a dynamic "virtual" CSS file was so that we could inject variables into it. I'll have a look at it again though.
Comment #3
urbanfalcon commentedIt is possible to inject variables into it while printing it straight to "head" - best of both worlds. Here's a diff file that shows how I altered my copy versus the official version now in CVS.
Comment #4
jjeff commentedAhh.. I see... You're sticking it all into the page html. Yeah that'll work too. But again, you've still got the effect of loading the code for the sIFR CSS files for each page load -- albeit that they're not actually separate files.
I think I'm going to look into creating a sIFR.css.php file that will load the Drupal variables. It will output its content directly so we should be able to control the browser caching stuff.
Comment #5
sunComment #6
zroger commentedwhat if after adding/editing a rule we generate a static css file and store the path in the db. this would move all performance hits to the rule creation stage avoiding any drupal/browser caching issues.
Any thoughts?
Comment #7
jjeff commentedGreat idea. Though, I'm not sure that there is really much overhead in loading the CSS stuff. If I remember correctly, it's just loading variables using variable_get() and all of the variables are already cached and loaded with each page. So there really aren't any "extra" database hits.
I think the larger problem (and this is really another issue) is that the dynamically generated .css files aren't outputting the correct headers in order for the browser to cache them. This means that the browser asks for every sifr-related .css file on every page call. Not cool.
Comment #8
jjeff commentedActually... no... the CSS caching problem isn't a separate issue... it's *this* issue. :-)
Here's some clues:
Drupal header (for ALL pages) gets set here:
http://api.drupal.org/api/4.7/function/drupal_page_header
notice the "Expires:" header
PHP header function should be able to override pre-existing headers before they are sent to the browser:
http://us3.php.net/header
see also:
http://us3.php.net/manual/en/function.headers-sent.php
It seems like you should be able to set the expiration headers in the same place that sifr is outputting the
header("Content-type: text/css");and things should work. But I've done a little experimenting and haven't gotten it to work yet.Good way of testing headers:
http://livehttpheaders.mozdev.org/
Comment #9
zroger commentedsounds good. thanks for pointing me in the right direction.
Comment #10
jjeff commentedAnother direction:
We could also write a CSS file to the 'files' directory. This might actually be the best solution because then Apache will take over and we won't have the problems we've been having.
It also *could* be interesting to experiment and see if we can get the sIFR module to download sIFR into the files directory itself!
We could be back to the same problems though, if Drupal's download method is set to "private", as everything from the files directory will get sent through Drupal before being sent to the user.
Comment #11
zroger commentedgood call. i hadn't thought about the 'private' option for the files directory.
Comment #12
sunThis issue is already fixed for 4.7 and 5.
Although $sitename is not taken into account in that fix I am closing this issue now. So using sifr in a multi-site setup won't work out. But let's wait until someone complains that and hopefully comes up with a patch already including a module update function...
Comment #13
(not verified) commented