I've added SSL to my backend, and the performance quickly went to
hell. I finally figured out that files served via SSL, particularly
the big files such as prototype.js, don't get cached (in the browser,
I guess [Safari]) when served via SSL. They get downloaded for each
page. Turn off SSL, and they are cached.
Problem is the stylesheet_link_tag and javascript_include_tag create
relative links, which means if the main url is https, it will server
those files with https.
Has anyone figured out a way around this, to only serve the action
with SSL, not the support files? This seems like a common problem
that at least BaseCamp would have run into.
Kinda doubt you wanna do that my friend. Worse than not caching some
of your files will be the annoying "this page is attempting to access
insecure files do you want to continue" (something like that) messages
that most of your users will receive if you do that.
I've added SSL to my backend, and the performance quickly went to
hell. I finally figured out that files served via SSL, particularly
the big files such as prototype.js, don't get cached (in the browser,
I guess [Safari]) when served via SSL. They get downloaded for each
page. Turn off SSL, and they are cached.
Problem is the stylesheet_link_tag and javascript_include_tag create
relative links, which means if the main url is https, it will server
those files with https.
Has anyone figured out a way around this, to only serve the action
with SSL, not the support files? This seems like a common problem
that at least BaseCamp would have run into.
If you try to serve the support files using anything other than SSL
most browsers will display nasty error messages to the users.
It is possible to cache images, javascript and stylesheets using
SSL though, just make sure the Cache-Control and Expires HTTP
headers are sent in each response.
Tim: Really, even with an official SSL certificate (from RapidSSL)? I
had done a quick test with mixed SSL/non-SSL content and didn't see
the warning, but maybe my browser was already set to ignore that.
Dan: How do I set the Cache-Control and Expires headers just for
images and stylesheets/javascript? I don't want the main content
cached - it needs to be regenerated each time. It looks like if I set
it in the controller it will be used for the action as well.
Tim: Really, even with an official SSL certificate (from RapidSSL)? I
had done a quick test with mixed SSL/non-SSL content and didn't see
the warning, but maybe my browser was already set to ignore that.
Yeah there's no doubt, most if not all of your users will get a warning
message if anything on your page is drawn from an insecure area. It
has nothing to do with who issued the certificate.
Dan: How do I set the Cache-Control and Expires headers just for
images and stylesheets/javascript? I don't want the main content
cached - it needs to be regenerated each time. It looks like if I set
it in the controller it will be used for the action as well.
What server are you using in front of your rails app? Apache, Nginx,
LightTPD or something else? Most server software has a way of
setting the Cache-Control and Expires header for a matching URL.
For example I use the following in my Nginx configuration:
Dan, I'm using Apache 2.2.3 for the static stuff and Mongrel. I have
found where you can cause caching at the Apache level, using
ExpiresByType. But doesn't it mess up your deploy? I mean, if you
change your stylesheet, users won't see it for 10 years (expires
10y;), because of the caching statement. How are you dealing with
that?
Append a version number to your CSS and javascript files maybe works?
Or don't cache it for ten years, only one day. But it doesn't sound
like a real solution.
Dan, I'm using Apache 2.2.3 for the static stuff and Mongrel. I have
found where you can cause caching at the Apache level, using
ExpiresByType. But doesn't it mess up your deploy? I mean, if you
change your stylesheet, users won't see it for 10 years (expires
10y;), because of the caching statement. How are you dealing with
that?
Dan, I'm using Apache 2.2.3 for the static stuff and Mongrel. I have
found where you can cause caching at the Apache level, using
ExpiresByType. But doesn't it mess up your deploy? I mean, if you
change your stylesheet, users won't see it for 10 years (expires
10y;), because of the caching statement. How are you dealing with
that?
If you're using the stylesheet_link_tag, javascript_include_tag,
or the image_tag methods from ActionView::Helpers::AssetTagHelper
the timestamp of the file will be appended onto the query string.
(the part after the ? in the URL) So you'll get URLs like this:
That means whenever you change the actual file, the query string
will change and "bust" the cache, causing the browser to download
what it thinks is a new file. Once downloaded the file should
be cached for a long period of time assuming the front-end server
is sending the correct caching headers.
Philip: I've used the assetpackager plugin before, but not on this
site. I will look at that and see if it helps.
Dan: I'm currently using the stylesheet_link_tag. Honestly, it seems
like in my testing if I use the ExpiresByType caching mechanism, the
caching *doesn't* break when the query string changes. When there is
no ExpiresByType, it seems to work correctly (in the http case).
Now you have me doubting myself. I need to do some more indepth
testing on this.
Question: I've been using Safari for testing, because I can easily see
what files are being downloaded for a page, the size of each one, and
their progress in downloading (Window -> Activity). So I can actually
see the progress as it downloads the 60K prototype.js file, and
therefore know that it's not coming from the cache.
Is there an extension in Firefox that will give the same information?
I would like to be testing with that as well.
Philip: I've used the assetpackager plugin before, but not on this
site. I will look at that and see if it helps.
I highly recommend this too if you have more than one stylesheet
and/or JavaScript file. Not only will it concatenate all
the stylesheets into one main stylesheet, and all the JavaScript
files into one Javascript file, it will compress them down so
they are transfered more quickly to the end user. Combine that
with gzip compression for the smallest transfer size possible.
Dan: I'm currently using the stylesheet_link_tag. Honestly, it seems
like in my testing if I use the ExpiresByType caching mechanism, the
caching *doesn't* break when the query string changes. When there is
no ExpiresByType, it seems to work correctly (in the http case).
Now you have me doubting myself. I need to do some more indepth
testing on this.
Here's an article that goes more in-depth into how the top four
browsers handle caching:
Question: I've been using Safari for testing, because I can easily see
what files are being downloaded for a page, the size of each one, and
their progress in downloading (Window -> Activity). So I can actually
see the progress as it downloads the 60K prototype.js file, and
therefore know that it's not coming from the cache.
I wouldn't believe everything you see in Safari's Activity menu. If you
"tail -f" your web server logs while accessing a page that links to
(properly configured) cached files, your web server should only show
the initial request and nothing for the cached files. Safari's Activity
menu will display all the requests identically regardless of whether the
content was retrieved from the browser cache or the server.
Is there an extension in Firefox that will give the same information?
I would like to be testing with that as well.
I'm not sure about a Firefox plugin. I use the server logs, since they
don't lie, and they work for every browser.