Part of the magic of TurboGears Widgets (and carried on in ToscaWidgets) is that you have a bundle of resources that come along with the widget object you add to your page. Generally, this is a couple of JavaScript files, some CSS files, and some images. This is certainly the case if you're using a Widget as part of creating a theme for a TurboGears application.
The resources are registered as a static directory in the framework (in TG, accessible as /tg_widgets/%(resource_name)s/ - usually resource_name is the module name), and you can then use JSLink and CSSLink and friends to provide the correct URL when referencing those resources. pkg_resources is used to provide the base path for the resources, thus allowing resources enclosed in .egg files to be found.
The widgets.py file for a TurboGears Widget generally contains this by default:
resource_dir = pkg_resources.resource_filename("tgsociable",
"static")
widgets.register_static_directory("tgsociable", resource_dir)
Having the request go through the framework - through an interpreter at all, can slow things down quite a bit. It's not so much a throughput issue as a latency issue - it takes longer to actually start sending the data for the resources. As you can imagine, the .egg file format isn't as fast as reading from the filesystem either.
mod_rewrite to the rescue, you say. The resources can just be served directly from the filesystem (and you'll make sure none of your widget packages is installed in a .egg file as opposed to the expanded form). Something simple like:
RewriteRule ^/blog/tg_widgets/widget/(.*) \
/.../lib/python2.4/site-packages/Widget-0.2-py2.4.egg/widget/static/$1
And that works. It works for quite some time, actually. Until, one day, when you have a pretty large update for your application, after painstaking testing on your QA environment, and suddenly you're still getting old copies of your resources. Your rewrite rule is still pointing to the old content.
The general way you get around external caches from serving up stale secondary resources (which, because they're static, often have high cache times) is to version them. If you get the new HTML file, you'll always get the new JS and CSS links, because those links include a version identifier.
This is pretty easy to do for widgets too. Instead of the default registration, you can embed the version number:
from gibebloggingpro import release
resource_name = "gibebloggingpro-%s" % (release.version,)
resource_dir = pkg_resources.resource_filename('gibebloggingpro', "static")
register_static_directory(resource_name, resource_dir)
Then, your rewrite rules look like:
RewriteRule ^/blog/tg_widgets/widget-0.2/(.*) \
/.../lib/python2.4/site-packages/Widget-0.2-py2.4.egg/widget/static/$1
Of course, every time you update, you do need to add new rules. And, well, those hard-coded long paths within site-packages suck a bit. But it's probably pretty trivial to copy all that stuff into an application-specific directory using a deployment script, and serve each version with a single mod_rewrite rule:
RewriteRule ^/blog/tg_widgets/widget-([^/]*)/(.*) \
/appdir/widget-$1/static/$2
ToscaWidgets even has a method to auto-generate an Apache configuration which uses Alias to serve your resources directly. (I use RewriteRule instead of Alias, because I use mod_rewrite to proxy to my application, and I can never remember the ordering of rules for mod_rewrite vs. Alias)
But unfortunately, currently, ToscaWidgets makes it hard to do the version component though - it requires that a module name be passed in, and it generates the web path from that. In theory, it could automatically look for a release.py file in the module name given, include that file, grab the version variable from it, and add it to the path - and nobody writing a widget need be any wiser.
You may also enjoy apache (2.2.x) mod_cache. It will store those expensive-to-render but static resources in a filesystem cache and serve them up from there. This approach is recommended with e.g. Plone, and I've found it works pretty well. Less complexity than having to update your mod_rewrite rules often.
Ooh, I'd forgotten about that - probably pretty trivial to set it up to only cache certain areas (like /tg_widgets/).
Having the version information in there will still make it that much more efficient.