- Web Developer
- Posts
- HTML Script Element Attributes: async vs. defer vs. type='module'
HTML Script Element Attributes: async vs. defer vs. type='module'
How do html script elements affect page loading
I believe you are no stranger to script elements in HTML. It has some properties such as async, defer, etc. Do you know what they do and the difference between them?
If the script element does not have any attributes added, then when the browser encounters the script, it will be loaded and executed immediately. After waiting for the execution to complete, it will continue to parse the following tags. This stage is called Parse HTML.
And if the script is large or time-consuming to execute, the page will be blank for a long time. Just like the screenshot above. This is especially common in some SPA front-end projects.
So for this situation, we can add attributes to script elements to optimize. Next, I divide script elements into three categories to explain separately:
Classic scripts
When we omit the type
attribute for script elements or configure as JavaScript MIME type (the only valid value currently text/javascript
), the script is a classic script.
<script type="text/javascript" async></script>
When the async attribute is configured for a classic script, the script is fetched immediately but does not block parsing HTML. Once the fetch is complete, it will be executed immediately, and if the HTML is not parsed at this time, it will be blocked.
<script type="text/javascript" src="/test.js" defer></script>
When the defer attribute is configured for a classic script, the script is fetched immediately but does not block parsing HTML. It is not executed until the HTML is parsed, but it blocks the DOMContentLoaded
event.
It should be noted that if this classic script does not use the src attribute, that is, an inline script, the defer attribute will have no effect.
Module scripts
When we configure type="module"
for a script element, then this script is a module script.
<script type="module"></script>
ESM can be used inside a module script, and even if the same module script is loaded multiple times, the script will only be executed once.
In the loading mechanism, its effect is the same as the defer of the classic script.
It is worth noting that if the module script is configured with the src
attribute, then unlike the classic script (which allows cross-domain), this module script needs to use the CORS protocol for cross-domain fetching.
<script type="module" async></script>
When the async attribute is configured for a module script, its loading mechanism is the same as the classic script configured with async.
<script type="module" defer></script>
When the defer attribute is configured for a module script, this attribute has no effect. Because module scripts are “defer” by default.
Other
When the type attribute value of the script element is not the above two valid values. Then the content in this script element (including src) will be discarded by the browser and will not be downloaded and executed.
Conclusion
The screenshot below clearly shows the difference between these types:
Image from WHATWG
If you find my content helpful, please consider subscribing. I send a weekly newsletter every Sunday with the latest web development updates. Thanks for your support!
Reply