Friday, November 26, 2010

A bit of refactoring and a whole lot better

It has been a while since I have posted anything new here or committed anything to the Steam repository, but I have not been idle. I have consolidated code into fewer classes, I have removed dependence on a database and sessions, I have taken advantage of the fact that PHP is a templating language, renamed objects for clarity, and fixed a bunch of other problems. I am feeling confident that Steam has reached a point where no more major changes will be necessary. There may only be some changes made to how widgets are manipulated. The following are some of the highlights of the changes made to Steam.

Views, Widgets, & Templates

PHP was originally developed to be a templating language used to create web pages. It has since matured into a full fledged programming language, but it's ability to create web pages remains very powerful. Some have attempted to push PHP to the backend and provide new templating engines (Smarty), but I don't understand the rationale behind doing that. People are already familiar with PHP, and it already does almost everything we need it to do. I initially had problems using PHP "as is" with Views (pages) because I needed to manage headers and defer output until the very end. So instead, I had pages manipulate a page object, insert widgets (which return strings) into it, and display it using a method. In an attempt to find a better solution, I leveraged output buffering to capture the output of views and widgets, allowing one to code them in "natural" PHP, and then output them using a template also written in natural PHP. While views can now output directly to the browser with no problems, their intended use is to identify a template and map widgets to different blocks in the templates. But, I maintained the flexibility for people who only need to create simple pages.


Static Resources

I was using Google's Page Speed tool to analyze a site I created using Steam, and I noticed a few suggestions related to caching static resources. Prior to the current version of Steam, Apache was given the responsibility of serving static files, but in order to make the most of browser caching, I had to do it using PHP. The first thing I did was update the Apache rewrite rules to forward all requests to Steam. Then, I added a special resource type "static" to directly serve files residing in the static directory to the client based on portal rules. This allowed me to set the right Expires/Cache-Control headers to get browsers to cache files. I then moved on to provide fingerprinting so I could set expiration dates to a year in advance. Fingerprinting involves adding a "fingerprint" to the name of a static resource in order to uniquely identify it. When this resource is requested, the server responds with the file sans fingerprint. The fingerprint is generated using the md5 of the file contents. Whenever the file is modified, a new fingerprint is attached to the resource. This forces browsers to retrieve the new version even though they had been told to cache the previous file for a year. This functionality is handled automatically by steam. Simply use the following method:
\Steam\StaticResource::uri('/images/background.png');

This method will return a relative uri to the resource with the proper fingerprint attached.

Special CSS Handling

A common way of improving transfer speeds of pages is to decrease the size of static resources using minification. However, working with CSS which has been minified is not feasible. The easiest alternative is to minify your CSS each time you modify it, and have your pages link to the minified version. That option is also not ideal because it involves a cumbersome and repetitive task which is bound to go wrong once in a while. My solution was to have Steam automatically handle this process. When using \Steam\View, you can identify the need of specific CSS files using \Steam\View::css('layout'). This will add layout to a list of CSS needed by the current page. When it is time to output the html to the browser, Steam will combine the contents of the list of CSS, minify the resulting string, and cache it. This file is then served to the browser when it requests the CSS file.

Steam as a Wordpress Plugin


A friend of mine and I have been having problems with Wordpress: developing a javascript based user interface and working with Wordpress themes is ugly and difficult to achieve the desired results. The Steam way of accomplishing these things is much nicer, but rewriting wordpress using steam would be a lot of work, break compatibility with existing plugins, burden us with the task of keeping it up to date and bug free, and not be an acceptable solution for some people who insist on using Wordpress.

The alternative was to integrate Steam with Wordpress as a plugin, and that's what we did. Steam is now delivered with an interface to hook into Wordpress. This can allow you to take over certain URI's using Steam instead. For instance, you could write your theme completely with Steam. There is still work to be done to wrap all the Wordpress objects with Steam Models and provide a basic "theme" so it will be usable out of the box, but it has been tested and it works as intended.