Load JavaScript optimally by utilizing defer.
Tags: javascript, webdev, beginners, programming
Published: 2022-05-22 07:57:41

This is by far the most important and awesome feature, and it's how you should load and import your JavaScript file from now on,  so let's get started with our teeny-tiny demonstration.

On modern websites, scripts tends to be `heavier` than HTML: they take longer to download and process. Whenever the browser loads HTML and encounters a `script` tag, it is unable to continue generating the DOM(Document Object Model) that's because the script must be loaded instantaneously.. External scripts are also treated similarly: the browser must first wait for the script to download, then run the downloaded script before continuing parsing the rest of the HTML.

So, initially, let's start by creating two files, one called `index.html` and the other called `script.js`, and inside the `index.html` file, add some simple boilerplate code by using the `HTML snippets` extension or you can simply copy the code mentioned below.

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Script: defer</title>
</head>
<body>
</body>
</html>
```

Now, inside our body, we'll just make a simple button with some text on it, and then inside our head, we'll add a script tag and import our `script.js` file which we just created.

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Script: defer</title>
    <script src="./scripts.js"></script>
</head>

<body>
    <button>Hello There!</button>
</body>

</html>
```

Once you've done that, open that index file in your browser with the live server, and you'll notice that there's a very basic looking button.

![Button Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptro8umgzj0jx502bily.png) 

Let's add some simple script to manipulate our button, so copy and paste the following JavaScript code into your `script.js` file.

```javascript
// scripts.js
const body = document.querySelector('body');
const btn = document.querySelector('button');

btn.style.display = 'block';
btn.style.position = 'absolute';
btn.style.left = '50%';
btn.style.top = '50%';
btn.style.transform = 'translate(-50%, -50%)';
btn.style.width = '200px';
btn.style.height = '100px';
btn.style.fontSize = '2rem';
btn.style.fontFamily = 'sans-serif';
btn.style.borderRadius = '10%';
btn.style.backgroundColor = '#8661d1';
btn.style.color = '#fff';
btn.style.border = 'none';
btn.style.outline = 'none';
btn.style.cursor = 'pointer';
btn.style.boxShadow = '0 0 10px #000';
btn.style.transition = 'all 0.5s ease-in-out';
btn.addEventListener('mouseenter', () => {
    btn.style.backgroundColor = '#FD5252';
});
btn.addEventListener('mouseleave', () => {
    btn.style.backgroundColor = '#8661d1';
});
btn.addEventListener('click', () => {
    body.style.backgroundColor = '#FD5252';

    setTimeout(() => {
        body.style.backgroundColor = '#fff';
    }, 1000);
});
btn.addEventListener('transitionend', () => {
    btn.style.backgroundColor = '#8661d1';
});
```
So, in this script, we first selected the `body`, then the `button`, then we apply a range of styles to that button, and then we proceed to add some event listeners, and finally we stated what that button should do in a specific event, and that's it, our button has been totally controlled using the absolute power of JavaScript.

![Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptro8umgzj0jx502bily.png) 

If you refresh your browser, you will notice no any changes on the site, it's because our script is up in the head, which is normally bad because it means that your JavaScript is loading way before the body itself. To fix this, simply add a `defer` inside the `script` tag. 

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Script: defer</title>
    <script src="./scripts.js" defer></script>
</head>

<body>
    <button>Hello There!</button>
</body>

</html>
``` 
We simply deferred our script in the above code, which means that our script guarantees that our overall body loads before running any of our JavaScript. So, once you've done that, your `index.html` file should look like this.

Now go to your browser and reload it, and you should see something similar to this.

![Button Demo GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgvlgrcvt7orri4jbwux.gif)
 
If we remove this `defer`, you'll find that our button doesn't work; instead, we get an error that says `cannot read property style of null`.

![Error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4o716xuz0tlj3gi2ta9h.png)
 
We'll get this error because when we get to our script tag, it stops parsing the rest of our html, but proceeds to the script, and only after that it continues parsing, which means the button never got added to our page. However, if we put `defer` in the script tag, it downloads all the JavaScript but then continues rendering everything, so it renders our button first, then begins rendering the complete page once the script has been downloaded.

People frequently put the script at the bottom, which works just fine, but the problem with this is that the download for the script doesn't start until the browser renders the entire page, which means it could slow down your website's loading speed and might make the site disorganized and unappealing.

Hence, by simply placing your JavaScript in the head and ensuring that `defer` is set, you will never have to wait for DOM events to load, nor will you have to deal with the inconvenient nature of placing your JavaScript towards the end of your body, which is tedious and awful.

So, from now on, keep your script at the `head`. All you have to do is just `defer` it, and it will do the same thing as putting your script towards the bottom, but it will help your webpage or website load even more faster.