The script HTML element has two asynchronous loading method that may be chosen via the presence of the async or defer attribute.
Async and defer are resource fetch instructions.
In a page load, the following processing occurs:
Type | Usage | Example | Processing |
---|---|---|---|
Inline / No Async/Defer | The script runs during parsing | analytics scripts | The browser runs the code, blocking the parser |
Async | The script should run as soon as possible | The browser downloads the script asynchronously while it continues to parse the HTML document. When the script finishes downloading, parsing is blocked while the script executes. | |
Defer | The script runs after the parsing | A video player | The browser downloads the script asynchronously while it continues to parse the HTML document. The script doesn't run until the parsing is complete and before the DOMContentLoaded event |
You can see in the code_demo that defer scripts are executed before the async scripts.
This is generally the case because defer blocks the DOMContentLoaded event and has therefore a higher priority in the queue of script to run.
The below diagram summarize how the user-agent (browser) will execute the HTML page:
where:
An async or defer script will execute before the page load event. They block it in some way. If you don't want this behavior, you should preload them and use/load them in your script when needed.
Because of that, they also have an impact on the largest content full paint
This demo shows you the event in order that occurs related to the code.
Note that because this is difficult to simulate a slow parsing, the defer and async script ends up in the execution queue together.
In this case, the defer script has a higher priority because it blocks the DOMContentLoaded event and its runs then first.
console.log("Hello from 'defer' script");
console.log("Hello from 'async' script");
<script>console.log('[1]: DOM is build')</script>
<script defer src="/_export/code/web/html/script_async_vs_defer?codeblock=0"></script>
<script async src="/_export/code/web/html/script_async_vs_defer?codeblock=1"></script>
<script>
console.log('[2]: Inline Wait Script is started');
let nowInline = new Date().getTime(), endInline = nowInline ;
while(endInline < nowInline + 3000) { endInline = new Date().getTime(); };
console.log('[3]: Inline Wait Script had ended');
</script>
<script>console.log('[4]: Lena is downloading');</script>
<img src="/_media/lenna.png" width="200px"/>
<script>console.log('[5]: Lena has been downloaded');</script>
<script>console.log('[4]: DOM was parsed')</script>
<script>window.addEventListener("load", () => console.log("page load event fired") )</script>