JavaScript loading: Prefer DEFER Over ASYNC

ASYNC and DEFER are similar in that they allow scripts to load without blocking the HTML parser which means users see page content more quickly. But they do have differences:

  • Scripts loaded with ASYNC are parsed and executed immediately when the resource is done downloading. Whereas DEFER scripts don’t execute until the HTML document is done being parsed (AKA, DOM Interactive or performance.timing.domInteractive).
  • ASYNC scripts may load out-of-order, whereas DEFER scripts are executed in the order in which they appear in markup. (Although there’s a bug that makes DEFER’s execution order questionable in IE⇐9.)

Even though ASYNC and DEFER don’t block the HTML parser, they can block rendering. This happens when they’re parsed and executed before rendering is complete and take over the browser main thread. There’s nothing in the spec that says they have to wait until rendering is complete. ASYNC scripts execute immediately once they finish downloading, and DEFER scripts execute after DOM Interactive.

[…]

DEFER always causes script execution to happen at the same time as or later than ASYNC. Presumably, scripts are made DEFER or ASYNC because they are less important for the critical content on the page. Therefore, it’s better to use DEFER so that their execution happens outside of the main rendering time.

DEFER scripts can never block synchronous scripts, while ASYNC scripts might depending on how quickly they download. Synchronous scripts are typically made synchronous because they are important for the critical content on the page. Therefore, it’s better to use DEFER so that synchronous scripts are not blocked from executing and their critical work is completed more quickly.