Load scripts in sequence with import(), async and IIFE
Tags: javascript, msal, powerpages, azure
Published: 2024-05-03 08:30:03

To load your scripts in a particular order you can use [import()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import), async...await and [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE). 

## Why the order matters

In some cases the order of loaded scripts is crucial for a portal to work. For example in my project I use [MSAL authentication library](https://learn.microsoft.com/en-us/entra/identity-platform/msal-overview) for identity-based authorization of requests to Azure Storage, Microsoft Dataverse, reading from Azure Active Directory (Entra), etc.  

So I need to be sure that the MSAL main script is loaded first, then the MSAL configuration and then the rest. Otherwise the process will fail.

## How

Add before closing `</body>` tag the following `<script>`

```javascript
<script type="text/javascript">
    (async() => {
        await import("/mustBe1.js")
        await import("/mustBe2.js")
        await import("/mustBe3.js")
    })()
</script>

// load order is irrelevant for this script
<script type="text/javascript" src="/orderDoesNotMatter.js"></script>
```

## Verification

Let's add some logging to see the order in real circumstances.

```javascript
<script type="text/javascript">
    (async() => {
        await import("/msal-browser360.js")
        console.log('msal-browser360.js loaded')
        await import("/msal-config.js")
        console.log('msal-config.js loaded')
        await import("/suppliers/suppliers-00.js")
        console.log('suppliers-00.js loaded')
    })()
</script>
<script type="text/javascript">
    console.log('very last script loaded') // will load first
</script>
```

### Console

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vc33izzgxo3esmxplnl.png)

### Dev Tools

We can also use Chrome Developer Tools -> Network tab to see the load order. Open it, `Empty Cache and Hard Reload` and sort the loaded files by Waterfall -> End Time.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/suc8lg8wserxeizn3tej.png)

## Advantages

Using `async` will load the page in parallel to the scripts, ie. the page rendering will not be blocked while waiting for the scripts to load in full. 

There is also [`async` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#async) available in the `<script>` tag which suits the same purpose, but the written sequence will rarely result in the same loading sequence.

By using `async...await` and `IIFE` we make it succinct. We could use `import().then(...)` instead since import() returns a promise.

As per **ECMAScript® Language Specification** dynamic `import()` is evaluated at runtime (ref. 5.2.3. Runtime Semantics in the specification), ie. script is parsed and checked for syntax errors when called, whereas the code from `<script>` tag (without `async` attribute) or static `import ...` is parsed and evaluated for errors in the extra step prior to runtime (5.2.4. Static Semantics early error rules).

So if the script is large, it would take longer to load the page due to the parser evaluating the code from `<script>` (withour `async` attribute), whereas with `import()`, the page will load first, and than the parser will evaluate the code when `import()` is called. Please correct me if I'm wrong...

In short, using `import()` will contribute to faster loading times.