We recently converted our entire JavaScript codebase to AMD modules that we load using RequireJS, the must-have “script loader that improves speed and code quality.”

After doing so, we quickly realized that following the guidelines indicated on RequireJS.org would have the opposite effect on our dashboard and make us lose the benefit of the biggest browser performance improvement ever: the look-ahead pre-parser.

RequireJS recommendation

On the RequireJS website you can find a snippet that shows how to include the library in the html head:

1
<script data-main="js/main" src="js/require.js"></script>

What’s happening here? The require.js script loads first, synchronously, then once parsed and executed, it programmatically requests the file referenced in the data-main attribute: js/main.js (the file that contains your code).

Since the second file loads asynchronously, (i.e. in the background) it doesn’t block the page rendering. This is why RequireJS can claim to speed up (most) websites.

sequential loading with RequireJS When using the data-main attribute, files are loaded in sequentially.

But it’s only true if the page is rendered on the server side and you only need JavaScript to enhance the user experience and add interactivity to your website. But if you’re building a single-page application, where the rendering is mostly done on the client-side using JavaScript templates, you surely don’t want to delay the very file that will make your page operational for your users.

parallel loading with RequireJS When using a regular script tag, files are loaded in parallel.

You lose the benefit of the biggest browser performance improvement ever!

There is another major drawback to not having your main JavaScript file inserted as a script tag in your HTML document: you will lose the benefit of the look-ahead pre-parser (also known as the browser preloader), the biggest improvement ever made to browser performance.

The preloader will detect all resources (js, css, images…) in the document and retrieve them in the background.

Unsurprisingly, browsers implement that feature differently. For example, Chrome re-prioritizes resources and loads the ones it considers critical first. Consequently, js files inserted at the very bottom of the document will be downloaded before other resources, even inline images inserted up front.

As a result, without you having to intervene, your website gets instantly faster. A study proved it can deliver a ~20% speed improvement.

This is why it may be a better option to include js/main.js as a script tag.

1
2
<script src="js/require.js"></script>
<script src="js/main.js"></script>

Using RequireJS to circumvent the pre-loader

Actually, there is a case where you may not want to use a script tag and RequireJS’s data-main attribute may come in handy: if you want to circumvent the pre-loader behaviour.

Let’s say you have an e-commerce website that heavily relies on images and your user base is predominantly using Chrome. As mentioned before, Chrome will prioritize scripts over inline images. If you want to ensure your images get loaded first, using RequireJS programmatic loading would be the way to go.

RequireJS is a must-have in your toolbox, a real game-changer. At HootSuite we use it and we love it!

But in our case, following the documentation blindly would have negatively impacted our site’s performance. Since the different components of our dashboard — like the social network streams or messages — are all rendered on the client-side, letting RequireJS load our main JavaScript file programmatically would have left our users staring at a blank layout for a longer time.

Interested in working on JavaScript at HootSuite? Apply here!

Thanks to Jeff Stautz, Gabriel Gosselin and Steve Mynett for their reviews!

2 comments
rpwverheij
rpwverheij

the information that is missing from this otherwise very interesting and relevant blog post (to me at least) is whether you can simply use 2 script tags like that, and / or if you need to change anything in the way you start up require.js with its init function. I'll go google for that now ...

Post Navigation