There are many ways to optimize the performance of a web page. A common way is to load JAVASCRIPT files asynchronously. Before we talk about asynchronous loading, let’s look at how browsers load JS files.
The browser loads the JavaScript script, mainly through the
- The browser starts parsing the HTML page as it downloads it. In other words, start parsing before you finish downloading.
- During parsing, the browser finds
<script>
Element, pausing parsing and transferring control of page rendering to the JavaScript engine.- if
<script>
Element references an external script, download the script and execute it, otherwise execute the code directly.- When the JavaScript engine completes execution, control is returned to the rendering engine and parsing the HTML page resumes.
When an external script is loaded, the browser pauses the page rendering and waits for the script to download and execute before continuing rendering. The reason is that JavaScript code can modify the DOM, so you have to cede control to it, or it can lead to complex thread races.
This loading method is called synchronous loading, or blocking loading, because when loading js script files, will block the browser parsing HTML document, wait until the download and execution is complete, will continue parsing HTML document. If it takes too long to load (for example, too long to download), the browser will “fake death” and the page will go blank. Also, you can’t manipulate the DOM in a synchronously loaded JS file in or you’ll get an error because the HTML hasn’t been parsed and the DOM hasn’t been generated yet. From this point of view, synchronous loading is often a bad experience.
Let’s take a look at several asynchronous loading methods.
-
will
<script>
The label on the<body>
At the bottom of theStrictly speaking, this is not asynchronous loading, but it is a common way to improve page performance by changing the way JS loads, so I’ll leave it at that.
Placing
-
defer
attributeSet the script file to defer by setting the defer attribute to the
This works only with
-
async
attributeThe async property is similar to the defer property in that it will start a thread to download the JS file, but unlike defer, it will execute as soon as the download is complete instead of waiting until the DOM is loaded, so it can still cause blocking.
Similarly, async is only applicable to external JS files, and document.write cannot be used in JS. However, for multiple JS files with Async, it cannot guarantee sequential execution like defer. Whichever JS file it downloads first will be executed first.
-
Dynamically create
<script>
The labelAsynchronously loading js files can be achieved by dynamically creating
(function(){ var scriptEle = document.createElement("script"); scriptEle.type = "text/javasctipt"; scriptEle.async = true; scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js"; var x = document.getElementsByTagName("head") [0]; x.insertBefore(scriptEle, x.firstChild); }) ();Copy the code
or
(function() {if(window.attachEvent){ window.attachEvent("load", asyncLoad); }else{ window.addEventListener("load", asyncLoad); } var asyncLoad = function(){ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script') [0]; s.parentNode.insertBefore(ga, s); }}) ();Copy the code
Of the two methods, the first method blocks the onLoad event until the completion of the execution, but now many pages of code perform additional rendering work during the onload, so it still blocks the initialization of some pages. The second does not prevent the onload event from firing.
DOMContentLoaded is triggered after the DOM has been parsed, and JavaScript can retrieve the DOM reference. However, some resources on the page, such as images and videos, have not been loaded, which is the same as the ready event in jQuery. The latter is when the page is fully loaded, including resources.
Having said these common ways to load JS scripts asynchronously, the last question is when to defer and when to async? In general, the choice between the two is whether there are dependencies between the scripts. If there are dependencies, the order of execution should be maintained, async should be used if there are no dependencies, and defer should be deactivated if there are any. Note that neither should use document.write, which causes the entire page to be cleared.
The following diagram illustrates the difference between synchronous loading and defer and Async loading, where the green line represents HTML parsing, the blue line represents network read JS scripts, and the red line represents JS script execution time: