DEV Community

Cover image for Master of HTML? Prove It with async and defer
Leapcell
Leapcell

Posted on

Master of HTML? Prove It with async and defer

Cover

Every web developer proudly claims to be proficient in HTML. But… do you really know the difference between async and defer in <script>?

These attributes are common in modern frontend web applications but are often overlooked.

Let's summarize first. In HTML, a <script> tag can be used in three ways, which will be explained one by one below:

  1. Default sequential execution: <script src='https://...'></script>
  2. Execute immediately after download: <script src='https://...' async></script>
  3. Execute after the document is fully parsed: <script src='https://...' defer></script>

<script>

Explanation

When a browser encounters a default <script> tag while parsing an HTML document:

  1. It blocks parsing of the remaining HTML.
  2. It loads the JavaScript script, and once the script is fully loaded, it executes immediately.
  3. After execution, HTML parsing resumes.

Consider the following example:

<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script src="https://.../Chart.min.js"></script>
    <script src="https://.../moment.min.js"></script>
    <script src="https://.../vue.min.js"></script>
  </head>
  <body>
    Page content 1
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Execution order:

  1. Logs console.log("First script");
  2. Downloads and executes the external script Chart.min.js
  3. Downloads and executes moment.min.js
  4. Downloads and executes vue.min.js
  5. Displays text content: Page content 1

Note

A default <script> executes scripts in order. If one script takes too long to execute, the subsequent scripts will be queued, and HTML parsing will be paused. This can result in a white screen until execution completes.

<script async>

Explanation

When the browser encounters a <script> tag with the async attribute:

  1. It does not block HTML parsing but asynchronously fetches the JavaScript script.
  2. Once the script finishes downloading, it immediately executes, pausing HTML parsing at that moment.
  3. After execution, HTML parsing resumes.

Consider the following example:

<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script async src="https://.../Chart.min.js"></script>
    <script async src="https://.../moment.min.js"></script>
    <script async src="https://.../vue.min.js"></script>
  </head>
  <body>
    Page content 2
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Execution order:

  1. Logs console.log("First script");
  2. Asynchronously downloads Chart.min.js, moment.min.js, and vue.min.js while HTML parsing continues.
  3. Once a script is downloaded, it immediately executes, pausing HTML parsing.
  4. HTML parsing resumes after script execution.

Note

Scripts with async pause HTML parsing during execution but not during download. If the HTML structure is simple, it may fully load before scripts execute, meaning "Page content 2" appears first, then scripts run.

If the HTML structure is complex and takes longer to parse, parsing may be interrupted when scripts execute.

<script defer>

Explanation

When the browser encounters a <script> tag with the defer attribute:

  1. It does not block HTML parsing but asynchronously fetches the JavaScript script.
  2. Once the script finishes downloading, it does not execute immediately.
  3. The script executes only after the entire HTML document has been fully parsed.

Consider the following example:

<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script defer src="https://.../Chart.min.js"></script>
    <script defer src="https://.../moment.min.js"></script>
    <script defer src="https://.../vue.min.js"></script>
  </head>
  <body>
    Page content 3
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Execution order:

  1. Logs console.log("First script");
  2. Asynchronously downloads Chart.min.js, moment.min.js, and vue.min.js while HTML parsing continues.
  3. Scripts do not execute immediately; they wait until HTML parsing completes and "Page content 3" is displayed.
  4. Executes the downloaded scripts in order.

Note

If multiple defer scripts are present, the browser downloads them in parallel. Regardless of download speed, execution order follows the sequence in the HTML document.

Mixed Usage

In real-world scenarios, different methods can be combined. Consider the following example:

<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script defer src="https://.../Chart.min.js"></script>
    <script async src="https://.../moment.min.js"></script>
    <script defer src="https://.../vue.min.js"></script>
  </head>
  <body>
    Page content 4
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Execution order:

  1. Logs console.log("First script");
  2. Asynchronously downloads Chart.min.js, moment.min.js, and vue.min.js.
  3. Because the HTML is simple, it fully loads before script execution, displaying "Page content 4" first.
  4. moment.min.js executes immediately after downloading.
  5. Chart.min.js and vue.min.js execute after HTML parsing completes.

Summary

  • Default <script> blocks HTML parsing and executes scripts in sequence.
  • defer does not block HTML parsing, ensures scripts execute in document order, and runs scripts after HTML parsing completes.
  • async may block HTML parsing but executes scripts in download order, which is unpredictable.

Best Practices

  • If a script is independent and does not rely on other scripts or resources, async is a good choice (though it may block parsing temporarily).
  • If scripts depend on each other, use defer to ensure order.
  • If both async and defer are present, async takes priority.

We are Leapcell, your top choice for hosting Node.js projects.

Leapcell

Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:

Multi-Language Support

  • Develop with Node.js, Python, Go, or Rust.

Deploy unlimited projects for free

  • pay only for usage — no requests, no charges.

Unbeatable Cost Efficiency

  • Pay-as-you-go with no idle charges.
  • Example: $25 supports 6.94M requests at a 60ms average response time.

Streamlined Developer Experience

  • Intuitive UI for effortless setup.
  • Fully automated CI/CD pipelines and GitOps integration.
  • Real-time metrics and logging for actionable insights.

Effortless Scalability and High Performance

  • Auto-scaling to handle high concurrency with ease.
  • Zero operational overhead — just focus on building.

Explore more in the Documentation!

Try Leapcell

Follow us on X: @LeapcellHQ


Read on our blog

Top comments (0)