An overview of the component framework architecture

After being inspired (as many others) by the work Lonely Planet did with their framework Rizzo we started thinking about how we could build a similar framework that would work with our web application platform IBM WebSphere Portal.

To not repeat mistakes already done by others we first looked at what Ian Feather wrote in his article What we would change about Rizzo in the beginning of January 2015 and also at the great collection of resources found at styleguides.io. We then sat down and tried to list the problems we wanted it to solve and the properties we wanted it to have.

Here’s roughly what we arrived at:

  • It should be a “living” component library where production code always mirrors the code in our documentation
  • We want to keep track of the components dependencies to CSS, JS and images
  • Deploying new versions of the framework should not require us to individually update each application where it is used

Technical architecture

WebSphere Portal is built on Java but we quite soon decided it would be much better to look for a solution that used a language agnostic approach so that we potentially also could use it outside of the WebSphere Portal plattform.

After comparing a few different solutions we decided to start experimenting with XML and back-end XSL transformations. After finding initial success we also adopted and decided to use a XML Schema Definition file to store component meta data and keep track its resource dependencies.

Here’s a short list of the pros and cons we see using XML, XSD and XSL transformations for our component framework.

Pros:

  • XML, XSL, XSD are well known and established languages
  • XSL-transformation implementations available in most programming languages
  • XSLT is a Turing-complete language, meaning there are no limitations to our transformations

Cons:

  • XML can be verbose (but it’s not really a problem, see why below)
  • Available implementations of the XSL-transformation might differ between platform and languages
  • The transformation requires the XML to be well-formed in order for the transformation to work (this isn’t inherently a bad thing but it’s easy to break an application)

The transformations from XML to HTML is done back-end by an application filter before anything is sent to the browser. In WebSphere Portal, you can set up which applications that should render through this filter.

The filter also accepts well-formed HTML (which it just passes through) so it’s possible to mix both XML and HTML. This can be useful if one application is in need of very specific HTML that we don’t see any value converting into a component.

The current way to handle the transformation with an application filter is a solution specific to the architecture of the WebSphere Portal platform, otherwise nothing in our framework architecture is tied to the current platform. If we, in the future, want to use the framework with another web application framework we’ll need to look at the best way to apply the transformation service with respect to its capabilities and limitations.

Example: the Card component

Everyone appreciates an example, so let’s look at the Card component.

XML for the Card component (goes into your application):

<gbg:card metadata=”external”> 
<gbg:element name=”url”>http://www.goteborg.se</gbg:element>
<gbg:element name=”header”>With image and copy</gbg:element>
<gbg:element name=”image”>/images/gorilla.jpg</gbg:element>
<gbg:element name=”text”>Lorem ipsum dolor.</gbg:element>
</gbg:card>

HTML generated from the XML above:

<article data-name="card" class="c-card">
<div class="c-card__meta">
<span class="c-card__tag c-tag c-tag--external">Extern kanal</span>
</div>
<figure class="c-card__image">
<img alt="" src="/images/gorilla.jpg?MOD=AJPERES"/>
</figure>
  <div class="c-card__head">
<h2 class="c-card__title">
<a class="c-card__title-link" href="http://www.goteborg.se">A simple card</a>
</h2>
</div>
  <div class="c-card__content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</article>

The rendered Card:

Sometimes the XML notation can seem quite verbose. Although a compact notation is sometimes preferable it is not the main purpose or goal here.

The important thing is that we are able to abstract the component so that it only consists of the content model, attributes for configuration options and meta data and the actual data.

The idea is that the content model of a component is more stable than the HTML markup (including CSS classes). If this holds true, the source code of the applications that uses the card component only need to be updated ones the content model changes, and not every time we need to change or add the CSS architecture och HTML mark-up.

CSS framework

We use the ITCSS framework for structuring our CSS with a BEM naming convention.

The CSS framework is separated from, but still closely related to, the component framework. Each component in the framework keeps track of which CSS and JS files it’s dependent of to render correctly, e.g. the Card component might have a dependency to components.card.css but also to elements.headers.css.

In the beginning the CSS framework and the component framework was more tightly coupled and I’ll discuss in more detail in a future post why we decided to separate them.

Versioning and deployment

Each component is versioned as a separate entity in our Git repository and the component framework itself currently has a stable and next branch. This allows us to bump up applications to new versions of the framework when they are ready and avoid applications breaking due to an upgrade that also requires changes in the XML.

Live documentation

A documentation of our component library can seen here (unpolished and experimental):
http://goteborg.se/wps/portal/component-framework/

We are just now starting to build applications using our component library that run in our production environment so the collection of components are currently few and many of them are experimental.

The documentation about each component in the Components page are generated automatically by parsing the XSD-file of each component which includes the usage examples, component metadata and dependencies.

Generating the documentation from the current version of the framework means that it is, per definition, always updated with production code.

Coming up

This was a brief overview of the architecture and there’s definitely a lot more to say about many of the topics above, especially about the iterations we went through to get where we are today. I’ll hope to cover this and many other topics in future posts.


This was part 2 in the publication: Our Story: Building a component library