Front End Tech Talk - Facebook
José M. Pérez / January 30, 2011
4 min read • 461 views
Yesterday I watched this Front End Tech Talk by Facebook. I found it very interesting because they explained how they faced the problem of having a lot of javascript code and how they managed to reduce it. I think this can be applied not only to a website of the size of Facebook's, but also any other project where we could refactor existing code.
We had about 1MB of JS on the homepage
They realized they had a problem with so much JS code and they worked at different levels to shrink it.
Haste
Haste is a package and dependency manager for CSS and JS files. In each file they specify the name of the package provided by the file and those files that are required to run the file. Thus, Haste can manage what files are needed to run a certain script.
This helps managing how files are requested and even which sets of files should be merged. This system was further explained by Xiaoliang "David" Wei at his talk about Static resource management & optimization that took place on December 2010 at Velocity China.
Bootloader
Bootloader consists of a JS library that helps loading and unloading static resources on demand. Not too far of RequireJS or LabJS. It uses dynamic script injection and executes a callback function once the resource is loaded.
The good point is that you can even suggest static resources that are not immediately needed but could be prefetched at background.
Primer
Makinde Adeagbo already talked about Primer at JSConf 2010 (slides).
A waterfall analysis showed that CSS resources where requested quite at the bottom and a lot of javascript on the head. Moving Javascript code to the bottom showed that the user interface would freeze while downloading/parsing/executing this code and that would provide a bad user experience. In some way, this is quite similar to what Yahoo! also found out, and I explained on my The not so good performance tips post.
They decided to rewrite their JS code so that they could load a small file at the top that would provide the common functionality needed (about 80% of the interactions). And they moved Javascript client code to PHP code on the server. Instead of calling to a function like this one:
Javascript code to build a dialog
they rewrote dialogs as anchors with a rel="dialog" attribute:
Simplified code to mark a link as a dialog
Basically they embraced progressive enhancement. This dialog links would be ajaxified later using a common Javascript code:
Adding a listener to manage click events on links marked as dialogs
And instead of letting Javascript set the title, content and the rest of dialog properties, it is the server the one that serves the dialog formatted as needed.
PHP chainable code to create a dialog and set different properties
It is like converting a jQuery widget plugin into an ajax call and let the server generate the widget content.
They used this same approach to replace chunks of similar Javascript code. In async calls that retrieved html to replace existing markup, they are now generating javascript code (using PHP) on the server side and executing it in the async response. And if the url that should be requested when clicking an ajaxified link is a different one, they specify it using a custom ajaxify
attribute. They also use this ajaxify
attribute to specify that a form should be ajaxified.
Like Makindo says,
if you are writing a site with tons and tons of Javascript it is very easy to forget about actual forms
All this common interactions are shown in the comments form:
An example of common interactions that in their comment form
The top red arrow indicates that Comment is a label, so clicking on it focuses the comment textarea.
Some sample Javascript code is available on https://gist.github.com/376039.
They managed to not only reduce Javascript size, but loading CSS on the top and being able to load Javascript at the bottom in an async mode.
This talk shows that sometimes it is necessary to return to the basic elements and build interactions from there, trying to find common functionality to reduce the code needed, and embracing progressive enhancement as a way to achieve it.