Order of loading scripts and modules

Excerpt

One page to show the loading behavior of scripts and conclusions.

There are the following script include mechanisms used in this page:

This creates the following output:

  script: start
  script: end
  getPrimes: start
      getPrimes: end
  module: start
  WaitDocument: interactive
  DOMContentLoaded event
  module: ready
  load event
  module: done
  

Blocking scripts

As expected the script in the header is executed first. When counting the script elements in the document only 2 of them are available so the document is not available completely.

The script at the end of the body is executed next but again the number of script tags and the document is still incomplete.

When using the blocking script from 06 Top Level Scripting you can see that both script blocks are blocking further loading and activation.

Using 'async' or 'defer' attributes on these script tags has no effect as defined by the standard.

You can activate and try this by adding a ?block parameter to the url.

You will see the counting the console output and that the loading other script blocks and modules are blocked.

Module scripts


<script type="module">
  import { getPrimes } from './00primes.js'
  ...
        

Module script are loaded in an async mode. What can be observed that the imported modules using the ES6 import statement are even executed before the start of the importing script.

When there are async functions in this script (as await is allowed) it may happen that the DOMContentLoaded and load events are dispatched even before the module script terminates. You can activate and try this by adding a ?wait parameter to the url.

You will see in the console output that the `module: count` and `module: done` will appear after the `load` event.

Use Modules after `load` is done

Sometimes it is important to be sure that at least the main document has loaded completely. This can be done using the trick from 06 Top Level Scripting to execute code by a trigger of the 06 Top Level Scripting using window.addEventListener("DOMContentLoaded", async f()); but wait...

Here is a Promise based function that waits for the document to be loaded completely.


// Promise to wait for document loaded completely.
function WaitDocument() {
  console.info('WaitDocument:', document.readyState);
  return new Promise(function (resolve, _reject) {
    if (document.readyState === 'complete') {
      resolve();
    } else {
      window.addEventListener('load', _e => {
        console.info('WaitDocument:', document.readyState);
        resolve();
      });
    }
  });
}
          

This can be used in module scripts by using a single statement: await WaitDocument();

You can activate and try this by adding a ?ready parameter to the url.

You will see in the console output that the `module: ready` and following infos will appear after the `load` event.

Summary

Using top level Scripts are too blocky so converting them into javascript modules is a good option.

See Also

Tags

JavaScript