Deep dive into the murky waters of script loading by Jake Archibald

In notebook:
Article Notes
Created at:
2016-05-29
Updated:
2016-05-29
Tags:
JavaScript DOM Performance
source: www.html5rocks.com

1. Include the script “as usual”

  <script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>
they’re downloaded in parallel and executed in order.
They block rendering until they are executed. Since they can do things like ​document.write​.

2. IE defer attribute

The ​defer​ attribute tells IE (version 4) that the script won’t touch the DOM, so this script will not block the rendering.

Unfortunately the script execution order is no longer guaranteed.

3. HTML5 async attribute


Similar to the ​defer​ attribute, it tells the browser that this script will not ​document.write​ but again the execution order of the scripts is not guaranteed. If one script relies on another, you can get bugs.
Ideally, you could just add your script tags and the browser would download them without blocking, but execute them in the order you specified them. This is not possible with plain HTML, you need libraries.

4. Libraries

  • RequireJS: wrap your script in a callback, that the library would call in the correct order.
  • others use ​eval()​ and XHR 
  • labJS: add an invalid ​type​ attribute to you script (<script type="script/cache" src="...”>​) Then once all of them are downloaded, labJS would change the MIME type and the browser would use its cache and execute them in the correct order. HTML5 broke this strategy, but LabJS has since been updated to count for this.
The problem, that an exta library also adds performance degradation (extra download, extra configuration, etc.)

5. Adding script programatically (dynamically)

Scripts added dynamically (by JavaScript) do not block the rendering, and you can set the ​async​ property to ​false​ and execute them in order.
  [
  '//other-domain.com/1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});
This script can (should) be add the ​head​ of the page. The browser of course has to understand the ​async​ attribute.
The disadvantages
It hides the script from preload scanners. You can add them back with the ​link​ element:
<link rel="subresource" href="//other-domain.com/1.js"><link rel="subresource" href="2.js”>​What if want one script (​dependencies.js​) to download and execute and then all the rest (​enhancements-1-10​) to execute in any order?
​async=false​ does not solve this, as the the last ​enhancement-n.js​ file will wait for all the other, non-related files to execute.