- [Instructor] When and how the browser loads
each JavaScript file it encounters has a significant impact
on both performance and functionality.
For this reason, we have the async and defer keywords
which instruct the browser to either load JavaScript files
asynchronously while rendering takes place,
and then execute them as soon as they're available,
or to load the files asynchronously
and defer execution until the DOM rendering is done.
Let's take a closer look at these two keywords
and how they work.
When the browser is presented with JavaScript,
either inline or from an external file,
it immediately stops its rendering process
because there's a good chance the JavaScript will impact
the HTML or CSS or both in some way.
This is what's referred to as render blocking.
And with big JavaScript files,
it can cause significant issues because everything stops
until the JavaScript is fully loaded and executed.
Additionally, JavaScript functionality often relies on
DOM elements already being present in the browser.
And since the browser reads the HTML document
from the top down,
if the JavaScript is executed before the DOM elements
it targets are rendered, errors occur.
This means whenever we load JavaScript
we have to consider several things.
When should the JavaScript be loaded?
When should the JavaScript be executed?
And does the JavaScript need to be loaded
and executed immediately or can it be deferred to later?
Think about this, if we add JavaScript
to the head of an HTML document,
it will always load and execute as soon as
the browser encounters it, which is always before
the body is rendered out.
This will always cause render blocking.
And there are very few scenarios where this is preferred.
In fact, I've asked JavaScript developers and experts
on social media, and nobody has been able to come up with
any practical example with render blocking
being intentional.
Traditionally, to prevent this render blocking
JavaScript has been added to the very bottom
of the body element,
but this is a hack and it's a bad one.
What happens now is the entire page will be loaded
before the JavaScript is even loaded
which just adds to the performance problems.
This is not an ideal solution.
The core problem is that the script tag,
out of the box, causes parsing to be paused.
It causes render blocking because as soon as the browser
encounters a reference to JavaScript,
it'll stop doing anything, download the entire script,
then execute the script, and then go back to rendering.
This is the problem.
The async and defer keywords change this behavior.
When we add async to the script tag,
the browser will load the JavaScript asynchronously
meaning it loads alongside the HTML parsing process.
When the script is fully loaded
the browser stops the rendering of the HTML
until the script is executed and then it continues.
Already we're seeing a significant performance enhancement
because the parsing isn't paused
while the script is being downloaded.
Oh, and a quick sidebar here.
The name asynchronous confused me
until I got a good explanation,
so I'm going to pass it on to you.
In JavaScript and other programming languages,
a synchronous event means one event happens after another,
in a chain.
Asynchronous means the events happen independently
of one another and one event doesn't have to wait
for another to complete before it takes place.
In the case of async JavaScript loading
the loading is asynchronous,
while the execution is synchronous.
Bottom line, use async anytime you're loading JavaScript
and you don't need to wait
for the whole DOM to be created first.
In other words, async should now be the default
for all JavaScript loading.
Defer is slightly different.
We're still loading the script asynchronously
when the browser encounters it without render blocking.
And then we literally defer the execution
of the JavaScript until the HTML parsing is complete.
This is effectively the same as placing the script tag
at the end of the body element,
except the script is loaded asynchronously,
and is therefore much better for performance
because we don't render out the entire HTML
and then go download the JavaScript.
The JavaScript is already downloaded.
So the basic rule of thumb here is use async
as the default and use defer if you need to wait
for the whole DOM to be loaded
before executing the JavaScript
or if the JavaScript can wait.
So here is your performance focused JavaScript
loading best practices.
Number one, call JavaScript
by placing the script tag in the head.
This is opposite of what we've been doing
for the past several decades
so it takes some getting used to.
Number two, use async as the default loading strategy.
Anytime you load JavaScript in the head,
always put async on there unless you have a reason
to use defer.
Number three, defer any scripts that need the DOM
to be fully built or scripts that you can defer
because they don't need to execute right away.
Number four, if you have a very good reason,
and again, I can't think of one for render blocking,
load your script in the head without async or defer.
And finally, if and only if,
you need to support older browsers
and you can't allow the browser to wait for things,
load your script in the footer the old way
and take the performance hit.