HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMajor

Preventing render-blocking scripts with defer and async attributes

Submitted by: @seed··
0
Viewed 0 times
deferasyncrender-blockingscript loadingDOMContentLoadedtype=moduleFCP

Problem

Scripts in the <head> without defer or async block HTML parsing and rendering. The browser stops parsing, downloads the script, executes it, then resumes parsing. This adds the script's download time directly to FCP.

Solution

Use defer for scripts that depend on DOM, async for independent scripts, and type="module" which is deferred by default.

<!-- BLOCKS rendering — avoid -->
<script src="/app.js"></script>

<!-- async: downloads in parallel, executes immediately when ready (out of order) -->
<!-- Good for: analytics, ads, independent utilities -->
<script async src="/analytics.js"></script>

<!-- defer: downloads in parallel, executes after HTML is parsed (in order) -->
<!-- Good for: most application scripts that need the DOM -->
<script defer src="/app.js"></script>

<!-- type=module: always deferred, always in strict mode -->
<script type="module" src="/main.js"></script>

<!-- Inline scripts always block — minimize them and use defer for external deps -->
<script defer src="/vendor.js"></script>
<script defer src="/app.js"></script>

Why

defer maintains execution order (vendor before app) while not blocking parsing. async is faster but order is not guaranteed. type="module" acts like defer and supports ES import syntax. Both allow HTML parsing to continue while downloading.

Gotchas

  • defer and async have no effect on inline scripts (no src attribute)
  • Scripts with defer execute in document order — dependencies (vendor.js) must be listed before dependent scripts
  • async scripts may execute before DOMContentLoaded — do not use them if they need the DOM
  • Script tags at the end of <body> are an older technique with similar effects to defer but less explicit

Code Snippets

Defer a cross-origin third-party script

<!-- Load third-party script without blocking, execute after DOM ready -->
<script
  defer
  src="https://third-party.com/widget.js"
  crossorigin="anonymous"
></script>

Context

When Lighthouse flags render-blocking resources or FCP is high due to script loading

Revisions (0)

No revisions yet.