Reintroducing AlloyUI (or meet Alloy 2.0)

Company Blogs February 4, 2013 By Eduardo Lundgren


For years Alloy has been known as the JavaScript Framework behind Liferay. This was great, because it's helped the project to grow a lot, but at the same time, it has restricted the project to a particular audience.

So now we want to present a different approach, we want Alloy to be recognised as a great JavaScript Framework used by many great projects, not just Liferay.

This may sound like a small change, but it's not. We're not just releasing a new version, we're rethinking all our engineering, all our communication, and our community approach as an open source project.

By doing that we can reach more contributors and when we improve Alloy we automatically improve Liferay.


So what's the big news?


New Website

First, we have a completely new website for you \o/

It's sexy, and it has a lot of new examples and tutorials. We decided to preserve the API Docs and Rosetta Stone because they're still great resources for general knowledge.

It was created using a NodeJS static generator and all documentation is now written in Markdown.

If you want to help us improve the website, please check the source code on Github (and remember to use GIFs :P).


Better Look & Feel

As you know, Alloy was built by engineers, but engineers aren't focused on design, right? That's why we decided to use the look & feel of Twitter Bootstrap, the most popular project on Github.



Last year we hired Zeno Rocha to help improve communication from AlloyUI and Liferay community with the engineering team, he will be our ears, so feel free to ping him about everything.

Also we added a few more communication channels, so you can now find us on Liferay Forums, Google Groups and Stack Overflow.


Faster Build System

We used Ant for a while, but as time goes by, faster build tools are made. So we're now moving to Shifter and Yogi, two awesome projects made by our friends at Yahoo!



AlloyUI is now hosted on a fast CDN, so you can use it easily by adding this url to your <script> tag.


Faster Download/Clone

The last version of Alloy repository was almost 800mb, now Alloy 2.0 is less than 10mb!


Fewer Components

The last version of AlloyUI had 73 components, but for this first release of AlloyUI 2.0, we're going to have 20 components.


What about the old components?

Don't worry, you can still find them on AlloyUI v1.7.0 if you need them, also you can find all documentation for it on


When is this going to be available on Liferay?

After this preview release, we're now going to be focused on upgrading AlloyUI into Liferay. So we'll communicate a date for this soon.


Why AlloyUI?

A lot of people ask, why they should invest their time on Alloy? Or why not just use jQuery with their gigantic ecosystem of plugins?

The thing is, DOM manipulation is just the tip of the iceberg when you're dealing with modern and highly scalable applications like Liferay. You'll probably need another library for templating (like Mustache/Handlebars), another for modular loading (like RequireJS/HeadJS), another for MVC structuring (like Backbone/Ember), another for UI components (like jQueryUI/ExtJS) and so on.

Well, AlloyUI comes with all of those things together. So there's no mess between different libraries, just a uniform API that makes your life easier. It's built on top of YUI3, an awesome project made by Yahoo!, and it's mantained by our highly qualified engineers at Liferay.


Next steps?

We're going to continue creating documentation for components, improving the website and taking all these changes to Liferay.

But the most important thing is, we want to hear what you think about this. Seriously, we could really use your feedback about anything, so go ahead and leave a comment on this blogpost or get in touch at Liferay Forums and Google Groups.


Wanna know more?

Join us on February 19 to a AlloyUI LIVE Session with Zeno Rocha.


Thanks :)

This wouldn't be possible without the help of Nate Cavanaugh and Brian Chan who believed in this idea. Also Djalma Araújo, Marc Lundgren, Ethan Bustad, Robert Frampton and Patrick Armitage helped insanely to create examples and tutorials for the website. And finally all our coworkers at the brazilian office for their support.

So we really want to say thank you guys, you're awesome!

Written by Eduardo Lundgren and Zeno Rocha.

Best Practices for Speeding Up Liferay

Company Blogs January 12, 2009 By Eduardo Lundgren

Only 5% of the end-user response time is spent fetching the HTML document. This result holds true for almost all web sites. The most part of websites spend less than 20% of the total response time getting the HTML document. The other 80+% of the time is spent dealing with what's in the HTML document, namely, the front-end. That's why the key to faster web sites is to focus on improving front-end performance. (thanks YAHOO!)

There are three main reasons why front-end performance is the place to start.

  • There is more potential for improvement by focusing on the front-end. Cutting it in half reduces response times by 40% or more, whereas cutting back-end performance in half results in less than a 10% reduction.
  • Front-end improvements typically require less time and resources than back-end projects (redesigning application architecture and code, finding and optimizing critical code paths, adding or modifying hardware, distributing databases, etc.).
  • Front-end performance tuning has been proven to work.

The performance golden rule is: optimize front-end performance first, that's where 80% or more of the end-user response time is spent.

Based on this "golden rules" me and Brian Chan decided (while the New Year's Eve party) to give a New Year's present for Liferay community and start a serie of performance improvements on our front-end.


1. Using CSS Sprites

CSS Sprites are the preferred method for reducing the number of image requests. Combine your background images into a single image and use the CSS background-image and background-position properties to display the desired image segment.

We have a new property called Defaults to true in normal usage and false in development. When the server startups, two files are automatically created on each image folder of your theme ".sprite.png" and "". These files are only recreated if needed. The taglibs are programmed to know to automatically read the "packed.sprite" and display that relative file on the "packed.png" if this feature is enabled.




This will significantly enhance load time (

You can perceive the benefits when you see in action, In a very simple page the number of requests decrease from 59 to 33 and the load time from 885ms to 811ms, in a big page with a lot of contents and hundreds of images it will cause a huge difference.

 ( without using )

  ( using )


 2. Cache Filter: Caching Strip Filter and Compress filter

Liferay Portal take advantage of server filters to manipulate headers, strip spaces from the content and even for gzip the content. These filters are doing a good job actually, however, these filters can run us into a problem. Filters are applied on each file on each request, it's very expensive for the server for both processing and memory.

In the old scenario, basically, the first filter applied was the Header Filter that is the most important because it saves the cache on the client-side, after the Strip Filter and the Compress Filter were being applied.

( Old scenario - Represents the priority/order without CacheFilter )

Now, in the new scenario, the CacheFilter instead of compressing / stripping per request on static data that has not changed, we know cache the bytes and content encoding and fetch it if the original data has not changed.

( New scenario - Represents the priority with CacheFilter )

This brings significant performance improvements to the server. This filter is cached on the server, it means - all users will take advantage of this technics, for instance, saving 50ms per request, and if the server has an avarage of 10000 request/hour this server will save 500000ms/hour (8.3 minutes/hour) of processing.

The graphic below resumes local tests I did today. Basically, the graphic compares how many milliseconds are spent when the filter are being used and when it's not, for different file sizes requests.

The results are promising, we need the community's help to test and see this improvements in action on live websites on a real enviroment.


3. Put Scripts at the Bottom

The problem caused by scripts is that they block parallel downloads. The HTTP/1.1 specification suggests that browsers download no more than two components in parallel per hostname. If you serve your images from multiple hostnames, you can get more than two downloads to occur in parallel. While a script is downloading, however, the browser won't start any other downloads, even on different hostnames.

We recommend if possible you use <footer-portlet-javascript> instead of <header-portlet-javascript> in your liferay-portlet.xml. By this way, we download the unecessary JavaScripts as after as possible.

It's important to remember that Stylesheets should be on top (vide, YAHOO).


4. For static components using "Never expire" header

There are two things in this rule:

  • For static components: implement "Never expire" policy by setting far future Expires header
  • For dynamic components: use an appropriate Cache-Control header to help the browser with conditional requests

A first-time visitor to your page may have to make several HTTP requests, but by using the Expires header you make those components cacheable. This avoids unnecessary HTTP requests on subsequent page views. Expires headers are most often used with images, but they should be used on all components including scripts, stylesheets, and Flash components.

Browsers use a cache to reduce the number and size of HTTP requests, making web pages load faster. A web server uses the Expires header in the HTTP response to tell the client how long a component can be cached. Keep in mind, if you use a far future Expires header you have to change the component's filename whenever the component changes. Or concatenate timestamps to the url.

Using a far future Expires header affects page views only after a user has already visited your site. It has no effect on the number of HTTP requests when a user visits your site for the first time and the browser's cache is empty. Therefore the impact of this performance improvement depends on how often users hit your pages with a primed cache. (A "primed cache" already contains all of the components in the page.) The number of page views with a primed cache is 75-85%. By using a far future Expires header, you increase the number of components that are cached by the browser and re-used on subsequent page views without sending a single byte over the user's Internet connection.


These are the most important stuffs we worked on these first days of 2009.
I'm sure these are important steps for improving the UI performance and they sounds like prosperation for our product.

Thanks guys!

Liferay PortletURL in JavaScript

Company Blogs December 20, 2008 By Eduardo Lundgren


Each more we feel the need of becoming more and more web 2.0, it sounds like a physics law to the "guys" that are trying to survivor arround the amazing applications that surround us across the urls.

Since few months ago I want to blog post about the new Liferay functionality that let you build PortletURLs using JavaScript only.

There are many places you can apply this new way of generating PortletURLs. Imagine a big list of links on your portlet, instead of download repeated hundreds urls from the server site you can simply create a javascript function that retuns a PortletURL instance and set on the fly the parameters you need. And now, you can simply integrate your pure javascript files (.js) with PortletURLs, without over passing it as parameter for your javascript constructor or another work-arround came from our misterious mind.

The usage of this functionality using JavaScript is very simple:

var portletURL = new Liferay.PortletURL();
portletURL.setParameter("key1", "value");
portletURL.setParameter("key2", "value");
alert( "that is the url: " + portletURL.toString() );

Or you can simply wrap it into a javascript function:

function createRowURL( row ) {
   var portletURL = new Liferay.PortletURL();
   portletURL.setParameter("rowNumber", row );

   return portletURL.toString();

alert( "row1: " + createRowURL(1) );
alert( "row2: " + createRowURL(2) );

If you want to know what methods you can play with the JavaScript Liferay.PortletURL you can take a quick look on the methods below:

  • setCopyCurrentRenderParameters: function(copyCurrentRenderParameters);
  • setDoAsUserId: function(doAsUserId);
  • setEncrypt: function(encrypt);
  • setEscapeXML: function(escapeXML);
  • setLifecycle: function(lifecycle);
  • setName: function(name);
  • setParameter: function(key, value);
  • setPlid: function(plid);
  • setPortletConfiguration: function(portletConfiguration);
  • setPortletId: function(portletId);
  • setPortletMode: function(portletMode);
  • setResourceId: function(resourceId);
  • setSecure: function(secure);
  • setWindowState: function(windowState);
  • toString: function();

I've also created some shortcuts for diferent kind of urls on the portal:

  • var actionURL = Liferay.PortletURL.createActionURL(); // = new Liferay.PortletURL('ACTION_PHASE');
  • var renderURL = Liferay.PortletURL.createRenderURL(); // = new Liferay.PortletURL('RENDER_PHASE');
  • var resourceURL = Liferay.PortletURL.createResourceURL(); // = new Liferay.PortletURL('RESOURCE_PHASE');
  • var permissionURL = Liferay.PortletURL.createPermissionURL(portletResource, modelResource, modelResourceDescription, resourcePrimKey);


I hope it help you guys. Enjoy!

Showing 3 results.