The script tag has three main attributes

  • Defer –> request the file immediately without blocking the rendering engine until the HTML parsing is complete

  • Async –> Request file immediately but do not block the rendering engine blocks the rendering engine after the file is loaded and executes the file contents immediately

  • Type –> Mainly the HTML5 standard type = ‘module’ allows the browser to parse the file as a module according to ES6 standards. The blocking effect defaults to defer, which can also be used with Async

demo

We prepare two JS files respectively for

/**
 * @file a.js
 */
 
console.log('module A');

setTimeout(() => {
  console.log('done');
}, 2000);
Copy the code
/**
 * @file b.mjs
 */
console.log('module B');

const nickname = await Promise.resolve('chou');
console.log(`My name is ${nickname}`);
Copy the code

We then introduce these two files in HTML

<body>
  <script src="./a.js"></script>
  <script src="./b.mjs"></script>
  <script>
    console.log('module C');
    const h1 = document.createElement('h1');
    h1.innerText = 'Hello Script';
    document.querySelector('#container').appendChild(h1);
  </script>
  <div id="container"></div>
</body>
Copy the code

We introduce a and B files in sequence and create dom elements at the bottom of the script

Now, the console is reporting an error and you can see why just by reporting an error message

Firstly, the syntax with top-level-await in B. Js is only supported in ES6 Module, so

< script SRC = “. / b.m js “> < / script > to change < script SRC =”. / b.m js “type =” module “> < / script >

Then document.querySelector(‘#container’).appendChild(h1) in inline-script fails to find the DOM element with the id container Because our DOM element is created after script

So the script tag should also add type = ‘module’ to delay its execution

Note here that both defer and async do not apply to inline-script, only to script tags with SCR attributes, so the scenario above would not apply to defer

The changed HTML looks like this

<body>
  <script src="./a.js"></script>
  <script src="./b.mjs" type="module"></script>
  <script type="module">
    console.log('module C');
    const h1 = document.createElement('h1');
    h1.innerText = 'Hello Script';
    document.querySelector('#container').appendChild(h1);
  </script>
  <div id="container"></div>
</body>
Copy the code

The page information is as follows

At this point, if we change the B module file to async mode

- <script src="./b.mjs" type="module"></script>
+ <script src="./b.mjs" type="module" async></script>
Copy the code

The following information is displayed

Use the explanation on MDN

For module scripts, if the async property is present, the script and all its dependencies are executed in the delay queue, so they are requested in parallel and parsed and executed as soon as possible

conclusion

  1. In order to avoidscriptThe tag blocking render engine should putscriptThe tag is placed at the bottom of the body element