There are three ways you can include a js script into a page.
<script src="default_loaded_script.js"></script> <script async src="async_loaded_script.js"></script> <script defer src="defer_loaded_script.js"></script>
Let's see what is the difference between them.
Loading a JS script the default way (without defer or async)
The browser will run your script immediately, before rendering the elements that are below your script tag. Your script will have access to all the content that was rendered only till that moment.
Not great for performance, as this means the user will need to wait for the script to download before seeing the full page. One tip is to set this at the bottom of the page so that the scripts are loaded last.
Loading a JS script using the defer attribute
<script defer src="defer_loaded_script.js"></script>
What this does is first to load the full html and ONLY after that, the script will get loaded.
This is great because we know for sure that the html will be 100% ready for the script to use. Note that not all images are necessary downloaded at this point. The
defer will wait just to the actual html not also for the images (and this is a good thing performance-wise).
You may want to use defer with core libraries like React, jQuery, or your main js code. It also gives us the certainty that the scripts files are loaded in the given order.
<script defer src="will_load_first.js"></script> <script defer src="will_load_second.js"></script> <script defer src="will_load_third.js"></script>
Loading a JS script using the async attribute
async attribute on a script tag means that the script will load at the same time as the rest of the html document.
This will not guarantee the fact that the full html is ready when the script runs. So for example, if you need in your script the reference to the footer of the page, that element may not be found.
Also async will not load the scripts in the given order. So let's say that your script uses jQuery it is NOT a good idea to write something like this:
//don't do this <script async src="jquery.js"></script> <script async src="script_that_uses_jquery.js"></script>
Use it only for scripts that don't need to have access to the full HTML tree. For example, a tracking script, analytics, or loading a newsletter widget at the middle of the page as Zell describes this really nice article.