Web Front end Performance optimization advanced--end article

Source: Internet
Author: User
Tags error handling script tag

Objective

In the previous article how to optimize the performance of the site, improve page loading speed, we briefly introduced the importance of site performance optimization and several Web site performance optimization methods (not seen can be a wild-poke link to the past to look at), then today we discussed in depth how to further optimize the performance of the site.

First, split initialize load

Split Initialize load--listen to the name feel tall on, not actually, the earth a little will be said to load the page needs a bunch of JavaScript files, divided into two parts: render the page necessary (page out, not him) and the rest. When the page is initialized, only the load must be loaded, and the rest is loaded.

In fact, in a real-world production environment, for most Web sites: When the page is loaded (Window.onload trigger), the JavaScript functions that have been executed only account for a small portion of the total load, such as 10% to 20% or less.

Note: The page loaded here refers to the window.onload trigger. What time does window.onload leave? Window.onload is triggered when the contents of the page (including pictures, styles, scripts) are all loaded into the browser, please make a distinction with jquery in $ (document).

We can see that most JavaScript functions are not executed after downloading, which creates a waste. Therefore, if we can use some way to delay the loading of this part of unused code, it can greatly reduce the amount of download when the page is initialized.

Splitting files

We can split the original code file into two parts: what is necessary to render the page (the page comes out, it doesn't work) and the rest; the page loads only the necessary, and the remaining JavaScript code is downloaded immediately after the page is loaded with nonblocking download technology.

Issues to be aware of:

1. We can split the code into a separate file by using certain tools (for example: Firebug) to get the functions that are executed when the page loads. So the problem is, some code will not be executed when the page is loaded, but it does have to be, such as conditional judgment code or error handling code. In addition, the scope of the JavaScript problem is relatively wonderful, these are to split the cause of great difficulties

2. Errors in the undefined identifier, such as when the loaded JavaScript code is executed, references a variable in the JavaScript code that we split the lazy load on, causing an error. Give me a chestnut:

When the page is loaded, the user taps a button (the original JavaScript file is split, only the code necessary to load the page is downloaded), and the code listening for this button has not been downloaded (because this is not required for page loading, so the split is degraded), So click there is no response or a direct error (Cannot find the event handler function).

Solution:

1. When the low-priority code is loaded, the button is not available (can be accompanied by a message);

2. Using the pile function, the pile function is the same as the original function name, but the function body is empty, so that the error can be prevented. When the remaining code is loaded, the pile function is overwritten with the original function of the same name. We can do it a bit harder: Record the user's behavior (click, drop Down), and then call the corresponding function according to the record when the remaining code is loaded.

Two, non-blocking load script

Most browsers can download the components needed for the page in parallel, but not for script files. When the script file is downloaded, it does not download any other content until its download is complete and the parsing is completed. This makes sense, because the browser does not know whether the script will manipulate the contents of the page, and secondly, the script that is loaded later may depend on the previous script, and if it is downloaded in parallel, the subsequent script may be downloaded and executed first, resulting in an error. So, before we talked about the script should be placed as close as possible to the bottom of the </body> location, just to minimize the impact of the entire page.

Next we discuss several techniques to make the page not blocked by the script's download:

1. Script Defer

<script type= "Text/javascript" src= "File1.js" defer></script>

Browser support: ie4+, Firefox 3.5+, and other new versions of the browser

Defer indicates that the script does not intend to modify the DOM and can be executed later.

2. Dynamic Scripting elements

var script = document.createelement ("script"), Script.type = "Text/javascript"; script.src = "A.js"; Document.body.appendChild (script);

The method of dynamically creating a script tag does not block other page processing, and the script can be downloaded in parallel under IE.

3, XHR (XMLHttpRequest) Eval

This method loads the script from the server in a non-blocking manner through XMLHttpRequest, and executes after the load is completed through Eval parsing.

1 var xhr = Getxhrobj (); 2  3 Xhr.onreadystatechange = function () {4     if (xhr.readystate = = 4 && Xhr.status = =) {5         eval (XHR). ResponseText); 6     } 7}; 8  9 Xhr.open (' GET ', ' text.js ', true); Xhr.send ("); function Getxhrobj () {     //...     return xhrobj;15}

This method does not block the download of other components in the page.

Cons: (1) The domain of the script must be in the same domain as the main page, and (2) the security of Eval

4, XHR injection

XMLHttpRequest Injection (XHR script injection) is similar to XHR eval, and is obtained by XMLHttpRequest for JavaScript. Once the file has been obtained, a script tag will be created to inject the resulting code into the page.

1 var xhr = new XMLHttpRequest ();  2 Xhr.open ("GET", "Test.js", true);  3 Xhr.send ("); 4 Xhr.onreadystatechange = function () {5     if (xhr.readystate = = 4) {6        if (xhr.status >= && Xhr.statu S < 300 | | Xhr.status = = 304) {  7             var script = document.createelement ("script");  8             script.type = "Text/javascript"; 9             script.text = xhr.responsetext;10             document.body.appendChild (script );       12}    

The content that XMLHttpRequest gets must be in the same domain as the home page.

5. src attribute of script element

1 var script = document.createelement (' script '), 2 script.src = ' http://a.com/a.js ' 3 document.body.appendChild (script);

This approach does not block other components, and it allows scripts to be obtained across domains.

6. IFrame Embedding Script

The IFRAME and other elements in the page are downloaded in parallel, so you can use this to embed the script that needs to be loaded into the IFRAME.

<iframe src= "1.html" frameborder= "0" width=0 height= "0" ></iframe>

Note: Here is 1.html instead of 1.js,iframe think this is an HTML file, and we embed the script to be loaded.

This approach requires the request URL of the IFRAME and the home page to be the same domain.

Iii. Integration of asynchronous scripts

Above we describe how to load the script asynchronously, improve the loading speed of the page. However, asynchronous loading scripts are also problematic, such as inline scripting relies on identities defined inside external scripts, so that when inline scripts are executed, the external script is not loaded and an error occurs.

So let's talk about how to implement asynchronous load scripts to ensure that the scripts are executed in the correct order.

Single external script and inline script

For example, an inline script uses an identifier defined by an external script, and an external script uses an asynchronous load to increase the load speed

$ (". Button"). Click (function () {    alert ("Hello");});         
<script src= "Jquery.js" ></script>

1. Script Onload

The script's OnLoad method is used to listen to whether the scripts are loaded, write inline code that relies on external files in the Init function, and invoke the Init function in the OnLoad event function.

Script.onload Support Situation:

IE6, IE7, IE8 do not support onload, you can use onreadystatechange instead.

IE9, IE10 triggers the onload event before triggering the onReadyStateChange event

IE11 (Edge) only triggers the OnLoad event

OnLoad is supported in other browser support, and both onload and onreadystatechange are valid in opera.

1 function init () {2     //inline code ... 3} 4 var script = document.createelement ("script");   5 Script.type = "Text/javascript";   6 script.src = "A.js"; 7 Script.onloaddone = false;     8  9 Script.onreadystatechange = function () {  ten      if (script.readystate = = ' Loaded ' | | script.readystate = = ' Complete ') &&!script.onloaddone) {  One         //alert ("onreadystatechange");         init ();       }14}15 script.onload = function () {     //Alert ("onload");     init (); 19     script.onloaddone = true;20}    document.getElementsByTagName (' head ') [0].appendchild (script);    

Here Onloaddone is used to prevent the initialization function from executing two times in IE9, IE10, and opera.

Script OnLoad is the preferred choice for consolidating inline scripts and external asynchronous load scripts.

Recommendation index: 5 stars

2. Hard-coded callback

Write inline code that relies on the external file in the Init function, modify the asynchronously loaded file, and add a call to the INIT function in the file.

Disadvantage: To modify external files, and we generally do not modify third-party plug-ins, lack of flexibility, change the callback interface, you need to modify the external script.

Recommendation index: 2 stars

3. Timer

Write inline code that relies on external files in the Init function, using the Timer method to check if the dependent namespace exists. If it already exists, the INIT function is called, and if it does not exist, wait for a period of time to check.

function init () {    //inline code ...} var script = document.createelement ("script");  Script.type = "Text/javascript";  SCRIPT.SRC = "Jquery.js";d ocument.getelementsbytagname (' head ') [0].appendchild (script);    function timer () {    if ("undefined" = = = typeof (JQuery)) {        setTimeout (timer,500);    }    else {        init ();}    } Timer ();

Disadvantages:

If the time interval set by settimeout is too small, it may increase the cost of the page, and if the time interval is too large, an external script will be loaded and the inline script will take a period of time to execute, resulting in a waste.

If the external script (jquery.js) fails to load, the poll will continue.

Increase maintenance costs because we need to use the specific identifier of the external script to determine if the script is loaded, and if the identifier for the external script changes, the code in the line needs to change.

Recommendation index: 2 stars

4, Window.onload

We can use the Window.onload event to trigger the execution of inline code, but this requires that the external script must be downloaded before the Window.onload event is triggered.

In the technology mentioned in the nonblocking loading script , theiframe embeds script, dynamic scripting element, and scriptDefer to meet this requirement.

1 function init () {2     //inline code ... 3}4 if (window.addeventlistener) {5     Window.addeventlistener ("Load", Init,false); 6}7 else if (window.attachevent) { 8     window.attachevent ("onload", init); 9}

Cons: This can block the Window.onload event, so it's not a good idea; if there are many other resources (pedagogical gardening, flash, etc.) on the page, the inline script will be deferred (even if the external script it relies on has already been loaded), Because Window.onload does not trigger.

Recommendation index: 3 stars

5. Downgrade using script

Come on, let's see what it looks like:

<script src= "Jquery.js" type= "Text/javascript" >    $ (". Button"). Click (function () {        alert ("Hello");    }); </script>

However, there is no browser to implement this method, in general, the external script (Jquery.js) loaded successfully, the code between the two tags will not be executed.

But we can improve it: Modify the code of the external script, let it search for itself in the DOM tree species, use innerHTML to get its own internal code, and then use Eval to execute, you can solve the problem.

Then we modify it so that it loads asynchronously, and it becomes this:

1 function init () {2     //inline code ... 3}4 var script = document.createelement ("script");  5 Script.type = "Text/javascript";  

In the external script we need to add the following code:

1 var scripts = document.getElementsByTagName ("script"), 2 3 for (var i = 0; i < scripts.length;i++) {4     if ( -1! = Scri Pts[i].src.indexof (' jquery.js ')) {5         eval (script.innerhtml); 6         break;7     }8}

That's it. However, the disadvantage is also obvious, we still need to modify the external file code.

Recommendation index: 2 stars

inline script, multiple external scripts depend on each other

Give me a chestnut:

Inline scripting relies on a.js,a.js dependent b.js;

This situation is more troublesome (OK, because I am too dish), briefly introduce the idea:

Make sure that A.js is executed after b.js, and inline scripts are executed after a.js.

We can use XMLHttpRequest at the same time to get two scripts asynchronously, if the A.js download completed first, then determine whether b.js download is complete, if the download is done, otherwise wait, a.js execution can invoke inline script execution. The B.js download is complete and can be executed.

The code is probably like this (to be correct):

 1 function init () {2//inline code ... 3} 4 5 6 var Xhra = new XMLHttpRequest ();   7 var xhrb = new XMLHttpRequest (); 8 var scripta, SCRIPTB; 9 var scripta = document.createelement ("script"); One scripta.type = "Text/javascript"; var SCRIPTB = document.createelement ("script"); Scriptb.type = "Text/javascript"; scripta = SCRIPTB = false;17 Xhra.open ("GET", "A.js", true); Xhra.send ("); xhra.onreadystatechange = function () {(xhr.readystate = = 4) {if (Xhr.status >= 2 XX && xhr.status < 300 | | Xhr.status = = 304) {Scripta.text = xhr.responsetext;24 Scripta = true;25 if (SCRIPTB     ) {document.body.appendChild (scripta); init (); 28} 29} 30 }31}; Xhrb.open ("GET", "B.js", true); Xhrb.send ("); xhrb.onreadystatechange = function () {(xhr.readystate = = 4) {PNS if (xhr.status >= 2 XX && Xhr.status< 300 | | Xhr.status = = 304) {Scriptb.text = xhr.responsetext;39 SCRIPTB = True40 Document.bo                 Dy.appendchild (SCRIPTB); if (scripta) {document.body.appendChild (scripta); 43  Init (); 44} 45} 46}47};

Iv. writing efficient JavaScript

As I've said before, we can poke around here and look at it.

Five, CSS selector optimization

1. Before we talk about selector optimization, let's start with a brief introduction to the selector type:

ID selector: #id;

Class selector:. Class

Tag Selector: A

Brother Selector: #id + A

Sub-selector: #id > A

Descendant selector: #id A

Pass-Compensation Selector: *

Property selector: input[type= ' input ']

Pseudo-class and pseudo-elements: a:hover, Div:after

Combo selector: #id,. Class

2. Browser matching rules

How do #abc > a match? One might think: Find the element with ID ABC first, then find the element of child element a!! Too Young,too simple!

In fact, the browser when the right-to-left matching selector!!! Then the above writing efficiency is low: First look at all the A in the page, the parent element is not the ID of ABC

Knowing the browser's matching rules, we can avoid the most expensive selectors as much as possible:

Avoid a wildcard rule

In addition to *, it also includes sub-selectors, background selectors, and so on.

And the combination of them is more counter-day, for example: Li *

The browser looks for all the elements of the page, and then one layer at a layer looking for his ancestors, to see if it is Li, which can greatly deplete performance.

The ID selector is not qualified

ID is unique, do not write like Div#nav so, not necessary.

Class Selector not qualified

We can further refine the class name, for example Li.nav written Nav-item

Try to avoid descendant selectors

Descendant selectors are usually the most expensive, and if possible, use a child selector instead.

Replace child selector

If possible, use a class selector instead of a sub-selector, for example

Nav > Li changed to. nav-item

Rely on inheritance

Understanding those attributes can depend on inheritance to avoid repeating the set rules.

3. Key Selector

The rightmost selector in the selector becomes the key selector, which has a major impact on the workload performed by the browser.

Give me a chestnut:

Div Div Li Span.class-special

At first glance, a variety of descendant selector combinations, performance certainly can not endure. In fact, a careful thought, the browser from right to left to match, if the page span.class-special element only one, that effect is not big ah.

In turn, if that's the case,

Span.class-special Li Div Div, although span.class-special is very small, but the browser matches from the right, find all the div in the page to look up in layers, the performance is naturally low.

4. Re-painting and reflow

The optimization of CSS selectors not only improves the efficiency of the page loading time, but also can get good results when the page reflow, redraw, then we say the redraw and reflow.

4.1, from the browser's rendering process

Parse HTML build dom tree → build render tree → layout render tree → draw render tree

1) Building the DOM tree

Generates a DOM tree from the obtained HTML code, each node represents an HTML tag, and the root node is the document object. The DOM tree species contains all the HTML tags, including non-displayed tags (display:none) and JS-added tags.

2) Build Cssom tree

Will get all the styles (browser and user-defined CSS) to remove the unrecognized (error and CSS hack), build into a cssom tree

3) Cssom and Dom are combined to generate a render tree, the render tree does not include hidden nodes including (Display:none, head tags), and each node has its own style property, rendering Each node of tree species into a box (box). Note: Elements with a transparency of 100% and Visibility:hidden elements are also included in the render tree because they affect the layout.

4) The browser draws the page according to the render tree

4.2. Redraw (repaint) and Reflow (reflow)

1) Redraw as part of the render tree or all because changes in the layout, display, and size of some elements in the page need to be rebuilt, which is reflow. Each page will have at least one reflow, which occurs when the page loads for the first time. During reflow, the browser invalidates the affected part of the render tree and reconstructs the part of the render tree, and after the reflow is completed, the browser redraws the affected part into the screen, which becomes redrawn.

2. When some elements in the render tree need to update the properties, which do not affect the layout, only affect the appearance, style of the element, such as color, Background-color, is called redraw.

Note: Reflow is bound to cause repainting, and repainting does not necessarily cause reflux.

4.3. When the reflux occurs:

Reflow is required when page layout and Geometry properties change. Browser reflow occurs in the following situations:

1. Add or remove visible DOM elements;

2, the element position changes;

3. Element size change-margin, fill, border, width and height

4, changes in content-such as text changes or changes in the size of the image caused by the width and height of the calculated value change;

5. Initialization of page rendering;

6, browser window size change--resize event occurs;

4.4. How to affect performance

Any node on the page that triggers reflow will cause its child nodes and ancestor nodes to be re-rendered.

Each time the redraw and reflow occurs, the browser redraws the part that needs to be rendered according to the corresponding CSS, and if your selector is not optimized, it will result in less efficiency, so the importance of optimizing selectors is evident.

Vi. use of IFRAME sparingly

When we write a Web page, we may use the Iframe,iframe advantage that it is completely independent of the parent document. The JavaScript file contained in the IFRAME accesses its parent document is restricted. For example, an IFRAME from a different domain cannot access the cookie of its parent document.

The most expensive DOM element

The cost of creating an IFRAME element is typically dozens of times times or hundreds of times times higher than the cost of creating other elements.

IFrame blocking onload Event

Usually we would like the Window.onload event to be triggered as much as possible for the following reasons:

    • We may have written the code for initializing the UI in the OnLoad event handler function;
    • When the onload event is triggered, the browser stops the "busy indicator" and the user feedback page is ready.
    • Some low-version browsers (IE6, IE7, IE8, Safari3, Safari4, Chrome1, Chrome2, and so on) only trigger the Unload event after the onload event is triggered. Sometimes, we bind some important actions with the Unload event of window. For example, reduce the code for memory leaks. If the onload takes too long and the user may leave the page, then unload may never be executed in these browsers.

Typically, the content in the IFRAME is not important to the page (such as third-party ads), and we should not delay the triggering of the Window.onload event for this content.

In summary, even if the IFRAME is empty, the overhead will be high, and he will block the onload event. Therefore, we should avoid using the IFRAME as much as possible.

Seven, picture optimization

In most Web sites, the size of the picture can often account for more than half, so the optimization of the picture can bring better results, but also, the optimization of the picture can be achieved without cutting site features to achieve the performance of the site.

1. Image format

Gif

Transparent: Allows the transparency of the binary type, either completely transparent or opaque.

Animations: Supports animations. Animations are made up of several frames.

Lossless: GIF is lossless

Progressive scan: When a GIF is generated, compression is used to reduce the file size. When compressing, pixel-by-line scanning allows for better compression when the image has many repeating colors in the horizontal direction.

Supports interlaced scanning

GIF is limited to 256 colors, so it is not suitable for displaying photos. Can be used to display graphics, but PNG8 is the best way to display graphics. Therefore, GIF is usually used only when animation is required.

Jpeg

Lossy

Animations and transparency are not supported

Supports interlaced scanning

Png

Transparent: PNG supports full alpha transparency

Animations: No cross-browser solution at this time

Nondestructive

Progressive scan: Similar to GIF, the image compression is higher than that of repeating color in horizontal direction.

Supports interlaced scanning

What interlaced scanning is:

When the network speed is slow, some images support interlaced scanning of images that are continuously sampled. Interlaced scanning allows the user to see a rough version of the image before the image is fully downloaded, eliminating the feeling of delayed loading of the page.

2. The strange phenomenon of PNG in IE6

All translucent pixels in the palette png are displayed as full transparency under IE6.

Alpha Transparent pixels in true-color PNG, which are displayed as background colors

3. Lossless image Optimization

PNG image optimization

PNG format image information is saved in "blocks", and for web reality, most blocks are not necessary and we can delete them.

Recommended tool: Pngcrush

JPEG image optimization

Peel metadata (comments, other internal information, etc.)

These metadata can be safely removed without compromising picture quality.

Recommended Tool Jpegtran

Convert GIF to PNG

Previously mentioned GIF function ate animation, completely can be replaced with PNG8, so we use PNG instead of GIF

Recommended Tool ImageMagick

Optimize GIF animations

Because there are many frames in the animation, and some of the content is the same on many frames, we can remove the repeated pixels from the continuous frames in the image.

Recommended tool: Gifsicle

4. CSS Sprite Optimization

If the site page is small, you can put the image in a super CSS Sprite

Look at Google using one:

Best Practices:

    • Merge by Color: A mutation of similar color is grouped together
    • Avoid unnecessary whitespace
    • Elements are arranged horizontally: slightly smaller than the vertical arrangement.
    • Limit color to 25 types (try to)
    • Optimize individual images first, and then optimize sprite
    • Reduce the number of anti-aliasing by controlling the size and alignment.
    • Avoid using diagonal gradients, which cannot be tiled.
    • Alpha transparent images in IE6 use Sprite alone
    • Change the gradient color every 2-3 pixels instead of each
    • Avoid scaling the image
    • If we need a small image, it is not necessary to reduce it in HTML after downloading a large image.
    • For example, we need a 100*100 image, we can now change the size of the server side of the image, so as to save the download traffic.

5. Avoid scaling the image

If we do not have a large image in the page, there is no need to download a large and then use CSS to limit his size.

For example, we need a 100*100 image, we can now change the size of the server side of the image, so as to save the download traffic.

Viii. Division of the primary domain

Before we talked about reducing DNS lookups, we should reduce the number of domains. But sometimes increasing the number of domains increases performance, the key is to find the key path to improve performance. If a domain provides too many resources and becomes a critical path, allocating resources to multiple domains (we become domain divisions) can make the page load faster.

When a single domain download resource becomes a bottleneck, you can assign resources to multiple domains. Increase the page speed by parallel download count.

such as YouTube serialized domain name: i1.ytimg.com, i2.ytimg.com, i3.ytimg.com, i4.ytimg.com

IP Address and host name

The browser's limit on the maximum number of connections per server is based on the host name on the URL, not the resolved IP address. Therefore, instead of having to deploy additional servers, we can create a CNAME record for the new domain. CNAME is only the alias of the domain name, even if the domain name is pointing to the same server, the browser will still open the maximum number of connections for each host name.

For example, we create an alias abc.com for Www.abc.com, which has the same IP address, and the browser will use each host name as a separate service side.

In addition, studies have shown that the number of domains increased from one to two performance will be improved, but more than two can have a negative impact. The final quantity depends on the size and quantity of the resource, but it is a good experience to be divided into two domains.

Web Front end Performance optimization advanced--end article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.