Why Using RequireJS As-Is Could Hurt Your Web Performance

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:

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.

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!


I'd argue that the most correct approach is a hybrid one, displaying simplistic elements immediately and containing the functions that manipulate those areas in one or two classes (perhaps one common to all areas of the site, and one for the current specific page or section) which would then declare dependencies on require.js libraries on an as-needed basis. 

I'd emphasize a vanilla-JS-first approach for its performance advantages across the board, and minimize the amount of libraries and classes loaded when the page is initially fetched. Yes, these classes amount to a total of two or three fairly-large fetches of JS files, but those will likely be Gzipped in transit, cached on receipt and will have negligible performance impact.

What content loads first shouldn't really be a question, IMHO: the best possible model is to load a small, simple DOM with minimal content, all of your JS libraries, then your CSS, and then progressively introduce elements onto the screen. I don't show anything except a gradient backdrop and a JS/CSS driven loading animation (no images necessary) while the first, most necessary resources are pulled in.

If you're using "smart" resources like image spriting, or (my preference) font icons, the size of the content you're loading isn't tremendous... and employed correctly, scales well to all platforms and resolutions with an incredibly small data footprint. The real geniuses of media can deliver your whole experience in less than 500Kb of content, progressively loaded as needed, tailored to the platform.


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 ...