- The position matters
- Async and Defer
- Performance comparison
- No defer or async, in the head
- No defer or async, in the body
- With async, in the head
- With defer, in the head
- Blocking parsing
- Blocking rendering
- domInteractive
- Keeping things in order
- Just tell me the best way
A script is traditionally included in the page in this way:
<script src="script.js"></script>
whenever the HTML parser finds this line, a request will be made to fetch the script, and the script is executed.
Once this process is done, the parsing can resume, and the rest of the HTML can be analyzed.
As you can imagine, this operation can have a huge impact on the loading time of the page.
If the script takes a little longer to load than expected, for example, if the network is a bit slow or if you’re on a mobile device and the connection is a bit sloppy, the visitor will likely see a blank page until the script is loaded and executed.
The position matters
When you first learn HTML, you’re told script tags live in the <head> tag:
<html>
As I told you earlier, when the parser finds this line, it goes to fetch the script and executes it. Then, after it’s done with this task, it goes on to parse the body.
This is bad because there is a lot of delays introduced. A very common solution to this issue is to put the script tag at the bottom of the page, just before the closing </body> tag.
In doing so, the script is loaded and executed after all the page is already parsed and loaded, which is a huge improvement over the head alternative.
This is the best thing you can do if you need to support older browsers that do not support two relatively recent features of HTML: async and defer.
When you first learn HTML, you’re told script tags live in the <head> tag:
<html>
<head>
<title>Title</title>
<script src="script.js"></script>
</head>
<body>
...
</body>
</html>
As I told you earlier, when the parser finds this line, it goes to fetch the script and executes it. Then, after it’s done with this task, it goes on to parse the body.
This is bad because there is a lot of delays introduced. A very common solution to this issue is to put the script tag at the bottom of the page, just before the closing </body> tag.
In doing so, the script is loaded and executed after all the page is already parsed and loaded, which is a huge improvement over the head alternative.
This is the best thing you can do if you need to support older browsers that do not support two relatively recent features of HTML: async and defer.
Async and Defer
Both async and defer are boolean attributes. Their usage is similar:
Both async and defer are boolean attributes. Their usage is similar:
<script async src="script.js"></script>
<script defer src="script.js"></script>
if you specify both, async takes precedence on modern browsers, while older browsers that support defer but not async will fallback to defer.
For the support table, check caniuse.com for async https://caniuse.com/#feat=script-async and for defer https://caniuse.com/#feat=script-defer
These attributes only make sense when using the script in the head portion of the page, and they are useless if you put the script in the body footer like we saw above.
if you specify both, async takes precedence on modern browsers, while older browsers that support defer but not async will fallback to defer.
For the support table, check caniuse.com for async https://caniuse.com/#feat=script-async and for defer https://caniuse.com/#feat=script-defer
These attributes only make sense when using the script in the head portion of the page, and they are useless if you put the script in the body footer like we saw above.
Performance comparison
No, defer or async, in the head
Here’s how a page loads a script without either defer or async, put in the head portion of the page:
The parsing is paused until the script is fetched, and executed. Once this is done, parsing resumes.
No, defer or async, in the head
Here’s how a page loads a script without either defer or async, put in the head portion of the page:
The parsing is paused until the script is fetched, and executed. Once this is done, parsing resumes.
No, defer or async, in the body
Here’s how a page loads a script without defer or async, but at the end of the body tag, just before it closes:
The parsing is done without any pauses, and when it finishes, the script is fetched and executed. Parsing is done before the script is even downloaded, so the page appears to the user way before the previous example.
Here’s how a page loads a script without defer or async, but at the end of the body tag, just before it closes:
The parsing is done without any pauses, and when it finishes, the script is fetched and executed. Parsing is done before the script is even downloaded, so the page appears to the user way before the previous example.
With async, in the head
Here’s how a page loads a script with async, put in the head tag:
The script is fetched asynchronously, and when it’s ready the HTML parsing is paused to execute the script, then it’s resumed.
Here’s how a page loads a script with async, put in the head tag:
The script is fetched asynchronously, and when it’s ready the HTML parsing is paused to execute the script, then it’s resumed.
With defer, in the head
Here’s how a page loads a script with defer, put in the head tag:
The script is fetched asynchronously, and it’s executed only after the HTML parsing is done.
Parsing finishes just like when we put the script at the end of the body tag, but overall the script execution finishes well before because the script has been downloaded in parallel with the HTML parsing.
So this is the winning solution in terms of speed 🏆
Here’s how a page loads a script with defer, put in the head tag:
The script is fetched asynchronously, and it’s executed only after the HTML parsing is done.
Parsing finishes just like when we put the script at the end of the body tag, but overall the script execution finishes well before because the script has been downloaded in parallel with the HTML parsing.
So this is the winning solution in terms of speed 🏆
Blocking parsing
async blocks the parsing of the page while defer does not.
async blocks the parsing of the page while defer does not.
Blocking rendering
Neither async nor defer guaranteeing anything on blocking rendering. This is up to you and your script (for example, making sure your scripts run after the onLoad) event.
Neither async nor defer guaranteeing anything on blocking rendering. This is up to you and your script (for example, making sure your scripts run after the onLoad) event.
domInteractive
Scripts marked defer are executed right after the domInteractive event, which happens after the HTML is loaded, parsed and the DOM is built.
CSS and images at this point are still to be parsed and loaded.
Once this is done, the browser will emit the domComplete event, and then onLoad.
domInteractive is important because its timing is recognized as a measure of perceived loading speed. See the MDN for more.
Scripts marked defer are executed right after the domInteractive event, which happens after the HTML is loaded, parsed and the DOM is built.
CSS and images at this point are still to be parsed and loaded.
Once this is done, the browser will emit the domComplete event, and then onLoad.
domInteractive is important because its timing is recognized as a measure of perceived loading speed. See the MDN for more.
Keeping things in order
Another case pro defer: scripts marked async are executed in casual order when they become available. Scripts marked defer are executed (after parsing completes) in the order in which they are defined in the markup.
Another case pro defer: scripts marked async are executed in casual order when they become available. Scripts marked defer are executed (after parsing completes) in the order in which they are defined in the markup.
Just tell me the best way
The best thing to do to speed up your page loading when using scripts is to put them in the head, and add a defer attribute to your script tag:
<script defer src="script.js"></script>
This is the scenario that triggers the faster domInteractive event.
Considering the pros of defer is seems a better choice over async in a variety of scenarios.
Unless you are fine with delaying the first render of the page, make sure that when the page is parsed the JavaScript you want is already executed.
Download my free JavaScript Beginner's Handbook
More browser tutorials:
The best thing to do to speed up your page loading when using scripts is to put them in the head, and add a defer attribute to your script tag:
<script defer src="script.js"></script>
This is the scenario that triggers the faster domInteractive event.
Considering the pros of defer is seems a better choice over async in a variety of scenarios.
Unless you are fine with delaying the first render of the page, make sure that when the page is parsed the JavaScript you want is already executed.
Download my free JavaScript Beginner's Handbook
More browser tutorials:
- Some useful tricks available in HTML5
- How I made a CMS-based website work offline
- The Complete Guide to Progressive Web Apps
- The Fetch API
- The Push API Guide
- The Channel Messaging API
- Service Workers Tutorial
- The Cache API Guide
- The Notification API Guide
- Dive into IndexedDB
- The Selectors API: querySelector and querySelectorAll
- Efficiently load JavaScript with defer and async
- The Document Object Model (DOM)
- The Web Storage API: local storage and session storage
- Learn how HTTP Cookies work
- The History API
- The WebP Image Format
- XMLHttpRequest (XHR)
- An in-depth SVG tutorial
- What are Data URLs
- Roadmap to learn the Web Platform
- CORS, Cross-Origin Resource Sharing
- Web Workers
- The requestAnimationFrame() guide
- What is the Doctype
- Working with the DevTools Console and the Console API
- The Speech Synthesis API
- How to wait for the DOM ready event in plain JavaScript
- How to add a class to a DOM element
- How to loop over DOM elements from querySelectorAll
- How to remove a class from a DOM element
- How to check if a DOM element has a class
- How to change a DOM node value
- How to add a click event to a list of DOM elements returned from querySelectorAll
- WebRTC, the Real Time Web API
- How to get the scroll position of an element in JavaScript
- How to replace a DOM element
- How to only accept images in an input file field
- Why use a preview version of a browser?
- The Blob Object
- The File Object
- The FileReader Object
- The FileList Object
- ArrayBuffer
- ArrayBufferView
- The URL Object
- Typed Arrays
- The DataView Object
- The BroadcastChannel API
- The Streams API
- The FormData Object
- The Navigator Object
- How to use the Geolocation API
- How to use getUserMedia()
- How to use the Drag and Drop API
- How to work with scrolling on Web Pages
- Handling forms in JavaScript
- Keyboard events
- Mouse events
- Touch events
- How to remove all children from a DOM element
- How to create an HTML attribute using vanilla Javascript
- How to check if a checkbox is checked using JavaScript?
- How to copy to the clipboard using JavaScript
- How to disable a button using JavaScript
- How to make a page editable in the browser
- How to get query string values in JavaScript with URLSearchParams
- How to remove all CSS from a page at once
- How to use insertAdjacentHTML
- Safari, warn before quitting
- How to add an image to the DOM using JavaScript
- How to reset a form
- How to use Google Fonts
Source:
No comments:
Post a Comment
If you have any doubts or questions, please let us know.