Your Script Loader is Killing You (Slowly)

Ben Regenspan

Kinja Performance Team

Our mandate: dramatically improve site performance on Gawker Media sites (Gawker, Jezebel, Deadspin...). Try to deliver readable pages to most users within 1 second.

Gawker Media Sites

Some Possible Performance Angles to Investigate

  1. Network requests/initial page load time
  2. Rendering performance
  3. Script execution / event-handler performance

Waterfall Analysis

A great way to begin any web performance effort is by analyzing waterfall charts. (Webpagetest.org is one fantastic free tool for viewing these)

Let's take a look at one!

Gawker.com Homepage Waterfall

(Simulated 3G Connection)

All requests

144 in total!

Total load time: 23.5s

All requests

ScriptsImagesFonts/Styles

Scripts

Third-party requests

Ad-related requests, mostly. 114 of our 144 requests...

Can we just remove all ads?

Like most media companies, a large chunk of our revenue comes from ads.

Revenue is used to pay software developers as well as some others involved in the business.

So we need some other way of making money.

Emergent Media Revenue Models

Proposal (facetious?) for alternate New Media revenue models

(The business side nixed both ideas)

Back to the waterfall...

Third-party requests

So, we can't eliminate these 114 requests right away. Let's focus on our first-party content...

First-party requests

Now we're looking at 30 requests, much more manageable.

(loaded in 18.8s)

First-party requests
(images)

First-party requests
(no images)

23 requests (loaded in 10.4s)

First-party requests
(script loader + main scripts)

Our script loader, require.js, followed by a 0.94s gap before the scripts it loads start to come in. 1.67s total delay.

3 requests (loaded in 8.4s)

Conventional Wisdom on Script Loading

This is bad:


<script src="dependency1.js"></script>
<script src="dependency2.js"></script>
          

This is good:


<script src="combined-scripts.js"></script>
          

This is acceptable:


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

But... concurrent is better

Two inline scripts (2.63s):
Two inline scripts, loaded in 2.63s
Concatenated (2.62s):
Concatenated scripts, loaded in 2.62s
Require.js (2.8s):
Require-packaged scripts, loaded in 2.8s

Summary

We used the power of waterfall charts to identify some key performance issues to investigate further:

  • A lot of third-party scripts — can we reduce # of vendors?
  • Images — can we improve image delivery/optimize further?
  • Blocking behavior of script loader — we are working on switching to Webpack.
    • (Almond.js is another alternative option for loading an AMD build)

Thank you!

Tools used for this presentation: