Skinning and personalization could be done in the user's browser, using XSL stylesheets, instead of on the server. I have done a mock up of how it could work: this test page should look like a standard MediaWiki page. But it's actually generated in your browser, using several XSL files - have a look at the source. Note that your mileage may vary - in Firefox it works for me, in MSIE the layout is a bit broken, doesn't work in Konqueror, didn't try Opera. If you like, add a comment and tell me how it works for you.
Contents |
The idea
Pages served by MediaWiki are heavily personalized, by the skin, the user's interface language, and user preferences. This makes it hard to apply any kind of caching to the pages served (Wikimedia projects like Wikipedia do cache pages, but only for anonymous users, because they all have the same settings). Merging all the different (more or less static) parts together into a personalized response is the job of the skin class. If the process could be moved to the client side, with all the different parts loaded and cached as appropriate, less redundant data would have to be sent, and more things could be cached.
Most modern browsers support XSL stylesheets (at least to some extent). This mechanism can be used to compose a page inside the browser, from different XML documents. Basically, the stylesheet would be the "skin" that puts together article content with per-user and per-site information. The per-page data would be the same for all users, so it could be cached in reverse proxies like the squid servers Wikimedia uses. The per-user data would be static for the user, and could thus be cached in the user's browser.
Getting all the pieces together
The nicest and cleanest way to implement this would be to compose an XML structure from the different parts (site-wide, per-page, per-user, etc), and apply an XSL transformation to it to generate displayable (X)HTML. The obvious mechanism to use for this is XInclude, but sadly, that's not supported in all browsers (Firefox doesn't seem to know it, I didn't bother to try others).
The alternative is to use the actual XML file served as a direct response to the browsers request for a wiki page as a stub, and pack all relevant informations into XSL files - XSLT does provide an include mechanism, and that works in all browsers. But we have to start somewhere, so the question is how to apply multiple XSL stylesheets to an XML file.
XSL stylesheets are applied to an XML document using the xml-stylesheet processing instruction. However, providing multiple such instructions doesn't quite work as expected. Firefox seems to somehow parse both, but declarations from one don't carry to the other, so it's useless.
Another way to do it would be to use an XSL stylesheet that is contained in the XML document. The XSL specification allow for fragments in stylesheet URLs (URI references), and also specifically allow the reference to consist only of a fragment, pointing to an element id in the XML document. The embedded stylesheet would then simply include the required parts. Sadly, this simply doesn't work.
The only thing left for now is to references a single stylesheet from the XML document, and generate a request-specific XSL document that includes the necessary parts. This means two requests for two different, dynamically generated documents, which kind of defeats the point of requesting less data and using mare caching. But for trying out the mechanism, it works for now.
Processing the data
Originally, the idea was to process an XML structure (composed from different places) with an XSL template (the skin). But since there's no working include mechanism for XML, the workaround is to compose the XSL instead. In XSL you can define variables (containing plain values or XML structures) that can be used later to generate the viewable HTML page. So, the per-page XSL would define variables for the page content, language links, categories, etc; the per-user XSL would define variables for the user name, personal tools, etc.
However, it appears that Firefox offers no way to process the contents of XSL variables with XSL rules (more precisely, it does not offer a way to interpret the variable's value as a node-set). Support for something like that seems to be targeted for Firefox 3.2 (sic!). This means that the variables must contain plain values, or HTML. This makes the XSL based skinning much less flexible, and requires some skinning logic (making toolboxes, link, and images) to be implemented on the server.
How the mockup works
The issues mentioned above made it a bit tricky to get it working - and Firefoxe's unusable error reporting for XSL problems didn't help (all it ever says is basically "something bad happened").
So, here are the part that make the mockup work:
- Test.xml
- This document is the direct response to a browser request. It can be cached only for anonymous users, if no request options where used. For technical reasons, much of the information that conceptually belongs here has been moved to Test.xsl.
- Test.xsl
- This document is a response to a spcific page request. It can be cached only for anonymous users, if no request options where used. This file contains information that was moved out of Test.xsl for technical reasons.
- Test.content.xsl
- This document contains a (more or less) abstract representation of a wiki page's contents: rendered HTML of the text, as well as categories, inter-language links, etc. This is the same for all users, as long as the page itself (or a template it uses) doesn't change. Per-user options for page rendering (such as numbered headings) should be handled with XSL.
- site.xsl
- Sitewide settings, generated mainly from LocalSettings.php. Rarely changes, fully cachable.
- messages-en.xsl
- Language file, generated from system messages. Rarely changes, fully cachable.
- John_Doe.user.xsl
- per-user settings, generated mainly from user preferences. Rarely changes, cachable on client, but not on squids.
- monobook.xsl
- Actual transformation rules to build HTML - i.e., the skin template. This is static for a given skin, and fully cacheable.
Conclusion
Using XSLT stylesheets to move all personalization to the client would be nice - it would allow less redundant data to be transferred, and would allow for more caching, especially for logged in users too. But XSLT is not yet supported by all browsers, and where it is supported, it is missing essentail features that would make this approach really nifty. Let's hope this changes soon.
As an afterthought: it would be a compromise to do the XSLT processing on the server side, but on the "first line of defense": Lightweight http servers that do nothing but loading XML and XSL files, apply the stylesheets, and send back HTML. This does not require any interaction with the database, maybe not even Apache or PHP. It could be done by a very terse binary CGI wrapper around libxml or something like that. This way, there would be complete control over the evaluation environment, and a nice XInclude-based approach could be used. Convincing libxml to send cookies when resolving URLs might be a problem though... Hm.
| Free Content |




(no comments yet)