[whatwg] Deferring javascript download and execution until after onload

Ian Hickson ian at hixie.ch
Wed Nov 28 20:01:59 PST 2012


On Mon, 17 Sep 2012, Andy Davies wrote:
>
> The script defer attribute allows us to defer JS until after 
> DOMContentLoaded (?) but it will still execute before onLoad

Actually defer="" defers to just before DOMContentLoaded, but <script> 
elements with a src="" attribute that are inserted into the document 
dynamically will load between DOMContentLoaded and onload, so you can do 
all your important loading in the DOMContentLoaded handler.

You can use this pretty easily:

   function loadScript(url) {
     var script = document.createElement('script');
     script.src = url;
     document.appendChild(script);
   }
   load('mylibrary.js');
   load('myotherlibrary.js');

This can be trivially extended to, e.g., add IDs and support the script 
being inserted by inline script in specific places:

   function loadScript(url, id) {
     var script = document.createElement('script');
     script.src = url;
     script.id = id;
     var target = document.currentScript;
     target.parentNode.insertBefore(script, target.nextSibling);
   }

   <!-- at the specific place you want this script -->
   <script>
     loadScript('mylibrary.js', 'mylib');
   </script>


On Mon, 17 Sep 2012, Jonas Sicking wrote:
> 
> There has been discussions about implementing a "noexec" attribute on 
> <script> which would just load the script but instead of evaluating it 
> as soon as it's available, simply fire the "load" event. There would 
> also be an additional .execute() function on the script which would 
> permit executing the script after it has been loaded.
> 
> This has mostly been discussed in a performance context where people has 
> expressed interest in loading scripts, while only waiting to execute it 
> until needed in order to avoid the costs involved in parsing and 
> executing the script.

The cost of parsing the script can be done async, even off the main thread 
in theory, so it's a non-issue. The only cost there could be is the cost 
of executing the script, and it's already trivial to offload that: just 
put all the code in a function, then call the function when you're ready.


> So far Hixie hasn't been interested in putting this into the spec 
> though, due to, as I understand it, not being convinced that it's needed 
> from a performance point of view.

It's not that it's not needed, it's that it's already possible. As far as 
I can tell, it adds nothing for performance.


> I'd personally be interested to see it implemented since people clearly 
> do load scripts dynamically and it would seem common for such scripts to 
> have dependencies on each other, which means that you have to be able to 
> execute them in a certain order.

It's already possible now to design scripts such that they don't run until 
you call them, so you could already do this:

   // library1.js
   // depends on library2!
   function loadLibrary1() {
     // do everything to load library1
   }

   // library2.js
   function loadLibrary2() {
     // do everything to load library2
   }

   <!-- index.html -->
   <script src="library1.js"></script>
   <script src="library2.js"></script>
   <script>
     function loadLibraries() {
       loadLibrary2();
       loadLibrary1();
     }
   </script>
   <body onload="loadLibraries()">

With ES6 import statements, this presumably gets even easier.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'


More information about the whatwg mailing list