Async vs Defer vs Default: Choosing the Right Script Loading Method

conver

In modern web development, understanding how the <script> tag loads and runs is very important for making pages work better and giving users a good experience. This article talks about three common script loading methods: default defer async. It uses example code and explains the order of execution to help developers understand their features and when to use them.

script default

Features

  • By default, when the browser sees a <script> tag while parse HTML, it stops HTML parse, loads, and runs the script right away.
  • After the script is loaded and run, the browser goes back to parse HTML.

script-default

case

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>script default</title>
  </head>
  <body>
    <script>
      console.log('script default')
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.13/vue.cjs.js"></script>
    <div class="bg-white">white background</div>
  </body>
</html>

So, the order of loading and running the whole HTML is:

  • Print script default
  • Download vue.js in a blocking way, stopping HTML parsing
  • Run vue.js
  • Continue HTML parsing

script async

Features

  • Scripts with the async attribute load without stopping HTML parsing.
  • After a script is loaded, it runs right away, which can stop HTML parsing at that time.
  • The order of running multiple async scripts is not certain. The one that finishes loading first runs first.

script-async

case

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>script async</title>
  </head>
  <body>
    <script>
      console.log('script async')
    </script>
    <script async src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.13/vue.cjs.js"></script>
    <div class="bg-white">white background</div>
  </body>
</html>

The order of loading and running the whole HTML is:

  • Print script async
  • Download vue.js in a non-blocking way, while HTML parsing goes on
  • Run vue.js, stopping HTML parsing
  • Continue HTML parsing

script defer

Features

  • Scripts with defer attribute load without stopping HTML parsing.
  • After a script is loaded, it does not run right away. Instead, it waits until the HTML parsing is done and then runs in order.
  • Multiple defer scripts run in the order they appear in the HTML.

script-defer

case

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>script defer</title>
  </head>
  <body>
    <script>
      console.log('script defer')
    </script>
    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.13/vue.cjs.js"></script>
    <div class="bg-white">white background</div>
  </body>
</html>

So, the order of loading and running the whole HTML is:

  • Print script defer
  • Download vue.js in a non-blocking way, while HTML parsing goes on
  • After HTML parsing is done, run the vue.js script

Mixed Usage

case

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>script defer</title>
  </head>
  <body>
    <script>
      console.log('script mixed')
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script
      async
      src="https://cdnjs.cloudflare.com/ajax/libs/dialog-polyfill/0.5.6/dialog-polyfill.min.js"
    ></script>
    <script
      defer
      src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.13/vue.cjs.js"
    ></script>
    <div class="bg-white">white background</div>
  </body>
</html>

The order of execution is:

  • Print script mixed
  • Download and run jquery.min.js in a blocking way, stopping HTML parsing
  • Download dialog-polyfill.min.js and vue.cjs.js in a non-blocking way, while HTML parsing goes on
  • Run dialog-polyfill.min.js, stopping HTML parsing
  • After HTML parsing is done, run the vue.js script

Conclusion

  • If a script is independent and does not depend on other resources, you can choose async.
  • If scripts depend on each other or need to run after HTML parsing, you should choose defer.
  • If a script must run right away and affects the following HTML content, use the default <script> tag.