JavaScript files (hereinafter referred to as script files) must be referenced by HTML files before they can be run in the browser. In HTML files, you can reference script files in different ways. We need to pay attention to the specific implementation of these methods and the performance problems that may arise from these methods.
When the browser encounters a (embedded) <script> tag, the current browser cannot determine whether javaScript will modify the page content. Therefore, the browser will stop processing the page, first execute javaScript code, and then continue parsing and rendering the page. The same situation occurs when the src attribute is added to javaScript (that is, external link javaScript). The browser must first spend time downloading the code in the external link file, then parse and execute it. In this process, page rendering and user interaction are completely blocked.
That is to say, when the browser parses the <script> tag (whether embedded or external), the browser downloads, parses, and executes the javaScript code in the tag first, the download and rendering of all subsequent page content are blocked.
Five script reference methods:
1. Conventional practices
2. Classic practices
3. Dynamic scripts
4. LABjs
5. requireJS
= Conventional practice
The most traditional method is to insert the <script> tag in the head tag:
However, this conventional approach hides serious performance problems. Based on the preceding description of the <script> tag feature, we know that in this example, when the browser resolves to the <script> tags style file and the <body> tag cannot be loaded, because the <body> tag cannot be loaded, the page cannot be rendered. Therefore, the page is blank before the javaScript code is fully executed.
<Script type = "text/javaScript" src = "example. js"> </script>
= Classic practice
Since the <script> label will block the loading of subsequent content, can the <script> label be put after all the page content to avoid this bad situation? Put all the <script> labels at the bottom of the <body> label as much as possible to avoid the impact on the download of the rest of the page.
However, scripts can be concurrently downloaded in IE8 + browsers, but in some browsers (even if the script file is placed at the bottom of the <body> tag ), the script on the page is still loaded one by one. Therefore, we need the next method, that is, dynamic script loading.
= Dynamic scripts
With the Document Object Model (DOM), we can create almost any part of the page
The code is as follows: |
Copy code |
Var script = document. createElement ('script '); Script. type = 'text/javaScript '; Script. src = 'file1. Js '; Document. getElementsByTagName ('head') [0]. appendChild (script ); |
The above code dynamically creates a <script> label of the external chain file1 and adds it to the
The file download and execution process does not block other processes (including script loading) on the page at any time ).
However, this method is also flawed. The script loaded in this way will be executed immediately after the download is complete, which means that the running sequence between multiple scripts is uncertain (except Firefox and Opera ). When a script is dependent on another script, an error may occur. For example, to write a jQuery code, you need to introduce the jQuery library. However, the jQuery code file you write may be downloaded and executed immediately, in this case, the browser reports an error, such as 'jquery undefined ', because the jQuery library has not been downloaded yet. Therefore, the following improvements were made:
The code is as follows: |
Copy code |
Function loadScript (url, callback ){ Var script = document. createElement ('script '); Script. type = "text/javaScript "; If (script. readyState) {// IE Script. onreadystatechange = function (){ If (script. readyState = "loaded" | script. readyState = "complete "){ Script. onreadystatechange = null; callback ();}}; } Else {// Other browsers Script. onload = function () {callback () ;};} script. src = url; Document. getElementsByTagName ('head') [0]. appendChild (script ); } |
The above code is improved by adding a callback function, which will be called after the corresponding script file is loaded. In this way, you can perform sequential loading. The syntax is as follows (suppose file2 depends on file1, file1 and file3 are independent of each other ):
The code is as follows: |
Copy code |
LoadScript ('file1. JS', function () {loadScript ('file2. JS', function () {}) ;}); loadScript ('file3. JS', function (){}); |
File2 starts to load after file1 is loaded, ensuring that file1 is ready before file2 is executed. While file1 and file3 are parallel downloads, which do not affect each other. Although the loadScript function is good enough, it is still a little unsatisfactory-by analyzing this code, we know that, the sequential loading in the loadScript function is implemented by blocking the loading of the script (as pointed out in the red text section above ). What we really want to achieve is: synchronous download of scripts and execution in the corresponding order, that is, parallel loading and sequential execution.
= LABjs
The LABjs library can help us implement "parallel loading and sequential execution". The Recommended syntax is as follows:
The code is as follows: |
Copy code |
<Script src = "LAB. js"> </script> <Script type = "text/javaScript"> $ LAB . Script ("script1.js"). wait () . Script ("script2-a.js ") . Script ("script2-b.js ") . Wait (function (){ InitScript1 (); InitScript2 (); }) . Script ("script3.js ") . Wait (function (){ InitScript3 (); }); </Script> = RequireJS <Script src = "require. js"> </script> <Script type = "text/javaScript"> Require ([ "Script1.js ", "Script2-a.js ", "Script2-b.js ", "Script3.js" ], Function (){ InitScript1 (); InitScript2 (); InitScript3 (); } ); </Script> |