XHP: a Frontend Engineer’s first impressions
XHP
What is it?
About a year ago, FaceBook open-sourced XHP, their front-end technology that sits on top of PHP. To say it “sits on top of PHP” is technically inaccurate because it is really just a PHP extension that allows the PHP parser to understand and use XML literals. It also understands the context in which this data exists (tags, attributes, elements, and string/PCData). The best part: XHP allows you to write custom tags that generate other tags/markup.
On the surface, this looks boring and maybe only valuable for an XML formats. NOT SO! You write code in XML literals and you can define any output for each XML tag you write.
After playing with XHP for a few days, I’ve come to the conclusion that it’s an incredibly useful tool for any web developer (frontend especially, but anyone who needs to write markup) that can afford to spare the extra server CPU cycles (there are documented ways to mitigate or avoid the performance hit). In many ways, XHP is a more intuitive replacement for XSL-t. It streamlines markup generation and reduces code redundancies.
Tell me more…
The compiled XHP PHP extension understands much of how XML is written (open/close/single tags, element/node nesting, attribute keys and values, PCDATA, etc.) HTML elements are not compiled into the extension, but rather classes defined in a PHP include file. This is nice in that it’s incredibly easy to modify the list of available tags (i.e. the differences between HTML4, XHTML1, HTML5). Essentially the html.php file (where the HTML tags are defined) becomes something like a DTD. Validation of XHP syntax (including most HTML validation rules) is enabled by default (and easily override-able for production servers). This gives you the best parts of validation during development (meaning extremely early feedback regarding W3c-valid markup without relying on the browser or your IDE’s syntax coloring) and performance (when validation is disabled in a production setting).
So far, I’ve only described XHP as a beurocratic validation layer, but the true power in XHP is the ability to create custom tags. I’m not talking about custom tags that are added to the markup… I’m talking about objects that generate groups of markup (or other tags).
Let’s start with an example.
Flash embed code is tedious to write and can be error prone. See the reccomended markup (from the SWFObject project at code.google.com):
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="780" height="420">
<param name="movie" value="myContent.swf" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="myContent.swf" width="780" height="420">
<!--<![endif]-->
<p>Alternative content</p>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
You might notice some redundancy; this happens for every SWF you need to include on a web page. I wrote an XHP class to avoid this tedious copy-paste nightmare. The code required to generate one of these Flash-embed blocks:
echo <djw:flash src="/path/to.swf" width="320" height="240" flashvars="foo=bar&fizz=buzz" />;
And the code required to define this custom tag:
/**
* :djw:flash
* Creates a cross-browser compatible Object that loads a Flash SWF (with Progressive Enhancement)
* note: IE Conditional comments and variable alt content not implemented
*/
class :djw:flash extends :x:element {
attribute string src, string width, string height, string flashvars;
protected function render() {
return <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width={$this->getAttribute('width')} height={$this->getAttribute('height')}>
<param name="movie" value={$this->getAttribute('src')} />
<object type="application/x-shockwave-flash" data={$this->getAttribute('src')} width={$this->getAttribute('width')} height={$this->getAttribute('height')}>
<p>Alternative content</p>
</object>
</object>;
}
}
What else can I do with it?
Userspaces. You can create a library of custom tags and namespace them by prefixing the tag name. I imagine FaceBook probably has many prefixes such as: “html:table”, “html5:section”, “fb:feed”, “fb:profile:interests”. “fbwap:comment”. Mixing of custom userspaces and W3C standards spaces (such as HTML4, HTML5, XHTML1, etc) allows you to create large amounts of valid, reusable markup extremely quickly. This re-usability also scales such that a Frontend engineer may write the guts of a userspace class (let’s take my “<djw:layout>” tag, for instance) and allow other developers to reuse/extend that code without actually looking into the guts.
What about the performance hit?
Performance with XHP varies on these factors:
- tag validation disabled/enabled (recommendation is to enable for development and disable for production)
- xhpize allows you to convert XHP to PHP before you deploy (eliminating the need to run the XHP extension on production)
- use of HipHop (which coverts+compiles PHP into C++ bytecode)
- the use of a PHP accelerator such as eA and APC
- caching of generated markup
I plan to do more extensive testing and profiling, but for now, you can look over Rasmus’ profile of XHP performance in a nearly trivial case.
Conclusions
IMHO, if you have a medium-large team building/maintaining a PHP-based web application, you should investigate whether XHPizing could improve your workflow and codebase. The performance hit seems to be heavy for web applications that are unable to cache rendered content, but may be offset by the reduced development costs from a more reusable, maintainable codebase.
No comments yet
Jump to comment form | comment rss [?] | trackback uri [?]