Async vs Defer vs Default: Choosing the Right Script Loading Method
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.
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.
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.
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.