DEV Community

loading...
Cover image for 
Do you need async and/or defer?

Do you need async and/or defer?

jmau111 profile image Julien Maury Originally published at blog.julien-maury.dev Updated on ・3 min read

These HTML attributes are said to be powerful. Let's check it.

Simple presentation

async and defer are simple attributes to use with your script tags:

<script defer src="./js/myjavascript.js"></script>
<script async src="./js/myjavascript.js"></script>
Enter fullscreen mode Exit fullscreen mode

It might seem self-explanatory, but I've seen a lot of misuses.

Do you need both? Where to use it? When to use it?

Simple definitions

Here are very light descriptions for these attributes:

  • async tells the browser to execute your JavaScript asynchronously
  • defer tells the browser to execute your JavaScript only after parsing the whole HTML document

Differences with/without these attributes

As we just saw, you have to add those attributes if you want the browser to act differently. Without async or defer, the browser stops parsing the document every time it finds an external js call, such as <script src="./js/myjavascript.js"></script>.

In this case, the browser pauses its parsing and fetches the js file to execute it. That's the reason why you often read that those calls are blocking.

In that perspective, it's a good practice to put your js calls at the end of the document, just before the </body> tag when it's possible, to reduce the amount of blocking resources. Lighthouse often tells you that ^^.

async to the rescue

The best-case scenario for async is when you need support for modern browsers only, and your script is entirely standalone, with no dependencies, so you don't expect results from other scripts to run your code.

Source: Caniuse

But I've seen the use of both attributes

It's not rare to see both attributes on the same tag:

<script defer async src="./js/myjavascript.js"></script>
Enter fullscreen mode Exit fullscreen mode

People may use that for ancient browsers where async is not supported, so it fallbacks to defer, as defer is pretty much older than async ( IE 6 for defer vs. IE 10 for async!!!)

I don't get it. Is it async, defer, or both?

There are subtleties you have to know.

If your scripts are very close to the closing </body> tag, it makes less sense to defer or async as the browser has almost finished its parsing. You won't significantly improve performances in this case.

Depending on the rendering engine, JavaScript is more or less blocking. In other words, the browser reduces blocking by dedicating threads to parse your js whether you've added the attributes or not.

With defer or async, the browser fetches your script asynchronously, but with defer, it will execute it only after parsing the whole HTML document, whereas, with async, it will execute it as soon as your js is ready.

As a result, the browser parsing may still pause even if you use async.

It's worth noting that if you defer several scripts, they will execute in the same order you've added them, even if it's deferred. It's not the same with async. You don't get the same level of control.

Potential misunderstandings

You won't eliminate all render-blocking issues by using defer or async. Don't forget to use the appropriate JavaScript event.

Deferred JavaScript executes BEFORE images and stylesheets are loaded and parsed. More precisely, it's before domContentLoaded.

Regarding async, don't write the following:

<script src="mylib.js" async></script>
<script src="myscript.js" async></script>
Enter fullscreen mode Exit fullscreen mode

If myscript.js needs functions set in mylib.js, it won't work as you might expect. Remember that as soon as the script is available, the browser executes it with async.

Wrap up

I've used the async attribute in particular cases only. I prefer the defer attribute, but I don't use it either if my script tags are very close to the closing </body> tag.

Again, the vast majority of modern browsers and rendering engines are pretty good at deferring and optimizing stuff, so it's probably more clever not to add anything than introducing nasty bugs, but these attributes are still impressive.

Discussion (2)

pic
Editor guide
Collapse
michaelcurrin profile image
Michael

Thanks for sharing.

You've covered how both work but let me add a suggestion when async is a good idea.

Async could load before the DOM had even started or way after it is complete. So it must not rely on something in the DOM (defer would be good in that case)

As you said, async tags don't follow an order so an async tag must not rely on another script or have another script rely on it. (Defer follows order as you said so works with dependence).

So it is independent of the DOM (what the user sees) and other tags, that means it must be used for something like Google Analytics. So your tracking doesn't block a user from viewing the page.

Another case is if you depend on something in the DOM but you fire the function at intervals or on an event.

I got both of those ideas from this article.

medium.com/javascript-in-plain-eng...

Async looks really specialized so I can see why you don't use it.

And defer is a good choice for something that interacts with the DOM but is not essential to the page looking presentable. Like a chatbot tab or image gallery.

Collapse
jmau111 profile image
Julien Maury Author

hi,

In the post :

The best-case scenario for async is when you need support for modern browsers only, and your script is entirely standalone, with no dependencies, so you don't expect results from other scripts to run your code

I think Google Analytics is compatible with that

In your comment :

if you depend on something in the DOM but you fire the function at intervals or on an even

I did not think about that usage here, thanks for sharing. I will check it.

And defer is a good choice for something that interacts with the DOM but is not essential to the page looking presentable. Like a chatbot tab or image gallery.

agree with you, defer is not critical. However, it can significantly improve performances in some conditions.