JavaScript & CSS

JavaScript Defer and Async Loading

Intermediate
High

How Browsers Handle Script Loading

When a browser encounters a <script> tag in your HTML, its default behavior is to stop everything — pause HTML parsing, download the script, execute it, and only then continue building the page. This is called render-blocking behavior, and it is one of the most common causes of slow Largest Contentful Paint (LCP) on WordPress sites.

The defer and async attributes on <script> tags change this default behavior, allowing the browser to continue parsing HTML while scripts download in the background. Understanding the difference between them is key to choosing the right loading strategy for each script on your site.

The Default: Parser-Blocking Scripts

A plain <script src="file.js"> tag without any attributes forces the browser to:

  1. Pause HTML parsing
  2. Download the JavaScript file
  3. Execute the JavaScript file
  4. Resume HTML parsing

Every millisecond spent in steps 1 through 3 is time your visitor spends staring at a blank or incomplete page. If a page loads five parser-blocking scripts, each one creates a sequential bottleneck.

Async: Download in Parallel, Execute Immediately

Adding async tells the browser to download the script in the background while continuing to parse HTML. However, as soon as the download finishes, the browser pauses parsing to execute the script immediately. This means:

  • Download does not block parsing (good)
  • Execution still blocks parsing (less good)
  • Scripts execute in whatever order they finish downloading — not the order they appear in HTML

Async is best suited for independent scripts that do not depend on other scripts or the DOM being fully built. Analytics snippets and tracking pixels are common candidates.

Defer: Download in Parallel, Execute After Parsing

The defer attribute also downloads scripts in the background, but delays execution until the HTML is fully parsed. Deferred scripts:

  • Download in parallel with HTML parsing
  • Execute after the DOM is complete, but before the DOMContentLoaded event
  • Execute in the order they appear in the HTML

Defer is the safer default for most WordPress scripts. It preserves execution order (important when scripts depend on each other, like jQuery and its plugins) while removing the parsing delay.

WordPress and Script Loading

Since WordPress 6.3, core adds the defer attribute to scripts registered through the standard wp_enqueue_script() system using a strategy parameter. However, many plugins and themes still enqueue scripts without specifying a loading strategy, which means those scripts load in the default parser-blocking way.

Some plugins also inject inline scripts or use wp_head hooks that bypass the enqueue system entirely. These scripts cannot benefit from defer/async unless the plugin developer updates their approach.

When Defer Can Cause Problems

Deferring a script that expects to run before the page renders — for example, scripts that modify the DOM during load to prevent a flash of unstyled content — can cause visual glitches. Some jQuery-dependent code also assumes jQuery is available immediately in the <head>, and deferring jQuery breaks that assumption. Testing after changing script loading behavior is important.

Tools That Can Help

Autoptimize can add defer to all aggregated JavaScript automatically. It provides a simple toggle but does not give per-script control, which can cause issues with scripts that need to execute early.

Perfmatters and Asset CleanUp both provide per-script control over defer and async attributes, along with the ability to disable scripts on specific pages. This granularity is more work to configure but less likely to break things.

Further Reading

Related Articles

Understand what makes a script render-blocking in the first place and how it affects LCP.
When your site loads dozens of scripts, defer and async become essential tools for managing the load.

Need help with this?

Mochyon specializes in WordPress Core Web Vitals optimization. We diagnose, fix, and verify — with a named human accountable for the result.

Get help from Mochyon