About
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.
Usage
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 |
Why defer scripts may run before async scripts ?
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.
Visualization
The below diagram summarize how the user-agent (browser) will execute the HTML page:
where:
- parser is the parser
- fetch is a browser fetch
- execution is the execution of the script
Blocking
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
Code Demo
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.
- The defer script that will be loaded with the defer attribute
console.log("Hello from 'defer' script");
- The async script that will be loaded with the async attribute
console.log("Hello from 'async' script");
- The HTML page that:
- loads the script (described above)
- execute inline javascript (this code will be called first)
<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>
- Output: