+ All Categories
Home > Technology > Enhance Web Performance

Enhance Web Performance

Date post: 19-May-2015
Category:
Upload: adam-lu
View: 1,710 times
Download: 0 times
Share this document with a friend
Popular Tags:
33
Enhance Web Enhance Web Performance Performance Adam Lu Adam Lu [email protected] [email protected] Y!ID: adamlu86 Y!ID: adamlu86 http://adamlu.com/ http://adamlu.com/
Transcript
Page 1: Enhance Web Performance

Enhance Web Enhance Web PerformancePerformance

Adam LuAdam [email protected]@alibaba-inc.com

Y!ID: adamlu86Y!ID: adamlu86http://adamlu.com/http://adamlu.com/

Page 2: Enhance Web Performance

The Performance Golden The Performance Golden RulesRules

80-90% of the end-user 80-90% of the end-user response time is spent on the response time is spent on the

front-end. front-end.

Page 3: Enhance Web Performance

High Performance Web High Performance Web SitesSites

► Make fewer Http RequestsMake fewer Http Requests► Style sheets at the top Style sheets at the top ► Placing scripts. Placing scripts. ► Avoid CSS Expressions Avoid CSS Expressions ► Make CSS and JS external Make CSS and JS external ► Minification Minification ► Make Ajax cacheableMake Ajax cacheable► Miscellaneous Tips Miscellaneous Tips

Page 4: Enhance Web Performance

Make fewer Http Requests Make fewer Http Requests

► Combine CSS and JavaScript files Combine CSS and JavaScript files ► Css Sprites – Used for snappy image replaceCss Sprites – Used for snappy image replace

ment ment Combine static images into a single image file. Combine static images into a single image file. Use Css to cut and place.Use Css to cut and place. CSS properties background-image and backgroCSS properties background-image and backgro

und-position are used. und-position are used. ►background:transparent url(“sprite.png”;) no-repebackground:transparent url(“sprite.png”;) no-repe

at at ►background-position: 0 -30px background-position: 0 -30px

Page 5: Enhance Web Performance

Style sheets at the top Style sheets at the top

► Use <link> tags to include stylesheets. Use <link> tags to include stylesheets. ► Neglect embedded styles and inline styles Neglect embedded styles and inline styles

too. too. ► Push style sheet inclusion into the head. Push style sheet inclusion into the head. ► User perception of the page loading faster User perception of the page loading faster

is important is important

Page 6: Enhance Web Performance

Placing scripts Placing scripts

► Move script inclusion as low as possible Move script inclusion as low as possible ► Don’t scatter inline scripts Don’t scatter inline scripts ► Progressive rendering. Progressive rendering. ► Scripts don’t download parallely. But in IE, it cScripts don’t download parallely. But in IE, it c

an be achieved by Dom inlucde. an be achieved by Dom inlucde. window.onload = function () { window.onload = function () { var script = document.createElement(“script”); var script = document.createElement(“script”); script.src = ...; script.src = ...; document.body.appendChild(script); document.body.appendChild(script); }; };

Page 7: Enhance Web Performance

Avoid CSS Expressions Avoid CSS Expressions

► Option available only in IE. Option available only in IE. width:expression(document.body.clientWidth < 550 ? width:expression(document.body.clientWidth < 550 ?

“450px” : “100%” ); “450px” : “100%” ); ► Use event handlers instead. Use event handlers instead.

Eg: element.addEventListener(‘<event>’, <handler Eg: element.addEventListener(‘<event>’, <handler to call>, <capturing/bubbling>). to call>, <capturing/bubbling>).

Eg: window.addEventListener(‘resize’, changeWidEg: window.addEventListener(‘resize’, changeWidth, true). th, true).

element.removeEventListener is used to remove the element.removeEventListener is used to remove the event. event.

In IE, attachEvent must be used instead.In IE, attachEvent must be used instead.

Page 8: Enhance Web Performance

Make JS &CSS external Make JS &CSS external

► Inline – Using <@include> or import Inline – Using <@include> or import make the html doc big. make the html doc big.

►External using <script> and <link> External using <script> and <link> tags tags Increases Http requests (bad)Increases Http requests (bad) Helps caching (good)Helps caching (good)

Page 9: Enhance Web Performance

Minification Minification ► Minify external javascript Minify external javascript

Remove comments and spaces Remove comments and spaces ► Minify inline scripts Minify inline scripts ► Obfuscation- Not recommended. Not safe Obfuscation- Not recommended. Not safe ► Let the dev code not be minified. Should Let the dev code not be minified. Should

have comments/spaces for maintainabilithave comments/spaces for maintainability. Use Tools before moving code to produy. Use Tools before moving code to production. ction. Js Min Js Min YUI Compressor.YUI Compressor.

Page 10: Enhance Web Performance

Make Ajax cacheableMake Ajax cacheable

► No synchronous requests. No synchronous requests. ► Use GET for AJAX Requests Use GET for AJAX Requests

Post is a two step process (Sending the headers first and then sePost is a two step process (Sending the headers first and then sending data)nding data)

► Favor JSON over XML as your data exchange format. Favor JSON over XML as your data exchange format. ► AJAX pattern: AJAX pattern:

► Update the UI when the request gets sent. Update the UI when the request gets sent. ► Lock the UI/data structures with the finest possible granularity. Lock the UI/data structures with the finest possible granularity. ► Let the user know that something is happening. Let the user know that something is happening. ► Let the user know why a UI object is locked. Let the user know why a UI object is locked. ► Unlock the UI/data structures when the outcome is successful. Unlock the UI/data structures when the outcome is successful. ► Handle error cases gracefully. Handle error cases gracefully.

► Lazy loading - http://ajaxpatterns.org/On-Demand_JavaLazy loading - http://ajaxpatterns.org/On-Demand_Javascriptscript

Page 11: Enhance Web Performance

Miscellaneous Tips Miscellaneous Tips

► Optimize Table Layout Optimize Table Layout ► Goal: allow the rendering engine to start rendering a table beGoal: allow the rendering engine to start rendering a table be

fore it has received all the datafore it has received all the data► Use table-layout:fixed Use table-layout:fixed ► Explicitly define a COL element for each columnExplicitly define a COL element for each column► Set the WIDTH attribute on each col Set the WIDTH attribute on each col

► Close Your HTML Tags to Speed Up ParsingClose Your HTML Tags to Speed Up Parsing► Regular expressionRegular expression

► Use regular expression literals. Use regular expression literals. Eg: if (/loaded|complete/.test(status)) {...} Eg: if (/loaded|complete/.test(status)) {...}

► Stick to simple patternsStick to simple patterns► In IE, Use Array.join(“”) rather than string concIn IE, Use Array.join(“”) rather than string conc

atenation atenation

Page 12: Enhance Web Performance

Miscellaneous TipsMiscellaneous Tips

► In case of changing lot of styles in js, try sIn case of changing lot of styles in js, try swapping styleclasses. wapping styleclasses. More maintainable: change the CSS class namMore maintainable: change the CSS class nam

e of an element. obj.className=‘<class>’; e of an element. obj.className=‘<class>’; ► Consider using the onmousedown event iConsider using the onmousedown event i

nstead of the onclick eventnstead of the onclick event► Document Tree Modification. Document Tree Modification.

InnerHTML Way is Faster than Usal WayInnerHTML Way is Faster than Usal Way

Page 13: Enhance Web Performance

Speed Up JavascriptSpeed Up Javascript

Page 14: Enhance Web Performance

There are four main reasons There are four main reasons why a script can take too long why a script can take too long

to executeto execute

►Too much happening in a loop. Too much happening in a loop. ►Too much happening in a function. Too much happening in a function. ►Too much recursion. Too much recursion. ►Too much DOM interaction. Too much DOM interaction.

Page 15: Enhance Web Performance

Too much happening in a Too much happening in a loop loop

► for(var i=0; i < items.length; i++){for(var i=0; i < items.length; i++){process(items[i]);process(items[i]);

}}► function chunk(array, process, context){ function chunk(array, process, context){

var items = array.concat(); //clone the arrayvar items = array.concat(); //clone the arraysetTimeout(function(){ setTimeout(function(){ var item = items.shift();var item = items.shift();process.call(context, item);process.call(context, item);if (items.length > 0){ if (items.length > 0){

setTimeout(arguments.callee, 100);setTimeout(arguments.callee, 100);}}}, 100);}, 100);

} }

Page 16: Enhance Web Performance

Too much happening in a Too much happening in a functionfunction

► function bubbleSort(items){ for (var i=items.length-1; i >function bubbleSort(items){ for (var i=items.length-1; i >= 0; i--){ for (var j=i; j >= 0; j--){ if (items[j] < items[j-1]){ var = 0; i--){ for (var j=i; j >= 0; j--){ if (items[j] < items[j-1]){ var temp = items[j]; items[j] = items[j-1]; items[j-1] = temp; }temp = items[j]; items[j] = items[j-1]; items[j-1] = temp; } } } } } } }

► function bubbleSort(array, onComplete){ var pos = 0; (fufunction bubbleSort(array, onComplete){ var pos = 0; (function(){ var j, value; for (j=array.length; j > pos; j--){ if (arnction(){ var j, value; for (j=array.length; j > pos; j--){ if (array[j] < array[j-1]){ value = data[j]; data[j] = data[j-1]; datray[j] < array[j-1]){ value = data[j]; data[j] = data[j-1]; data[j-1] = value; } } pos++; if (pos < array.length){ setTimeoa[j-1] = value; } } pos++; if (pos < array.length){ setTimeout(arguments.callee,10); } else { onComplete(); } })(); } ut(arguments.callee,10); } else { onComplete(); } })(); }

Page 17: Enhance Web Performance

Too much happening in a Too much happening in a functionfunction

► function fibonacci (n) { return n < 2 ? n : fibonafunction fibonacci (n) { return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); };cci(n - 1) + fibonacci(n - 2); };

► function memoizer(memo, fundamental) { var function memoizer(memo, fundamental) { var shell = function (n) { var result = memo[n]; if (tyshell = function (n) { var result = memo[n]; if (typeof result !== 'number') { result = fundamentapeof result !== 'number') { result = fundamental(shell, n); memo[n] = result; } return result; }; rl(shell, n); memo[n] = result; } return result; }; return shell; }; eturn shell; }; var fibonacci = memoizer([0, 1], function (recuvar fibonacci = memoizer([0, 1], function (recur, n) { return recur(n - 1) + recur(n - 2); }); r, n) { return recur(n - 1) + recur(n - 2); }); fibonacci(40);fibonacci(40);

Page 18: Enhance Web Performance

Too much recursionToo much recursion

► function merge(left, right){ var result = []; while (left.length > 0 && rifunction merge(left, right){ var result = []; while (left.length > 0 && right.length > 0){ if (left[0] < right[0]){ result.push(left.shift()); } else { rght.length > 0){ if (left[0] < right[0]){ result.push(left.shift()); } else { result.push(right.shift()); } } return result.concat(left).concat(right); }esult.push(right.shift()); } } return result.concat(left).concat(right); }

► //recursive merge sort algorithm //recursive merge sort algorithm function mergeSort(items){ if (items.length == 1) { return items; } vafunction mergeSort(items){ if (items.length == 1) { return items; } var middle = Math.floor(items.length / 2), left = items.slice(0, middle), r middle = Math.floor(items.length / 2), left = items.slice(0, middle), right = items.slice(middle); return merge(mergeSort(left), mergeSoright = items.slice(middle); return merge(mergeSort(left), mergeSort(right)); }rt(right)); }

► //iterative merge sort algorithm //iterative merge sort algorithm function mergeSort(items){ if (items.length == 1) { return items; } vafunction mergeSort(items){ if (items.length == 1) { return items; } var work = []; for (var i=0, len=items.length; i < len; i++){ work.push([itr work = []; for (var i=0, len=items.length; i < len; i++){ work.push([items[i]]); } work.push([]); //in case of odd number of items for (var liems[i]]); } work.push([]); //in case of odd number of items for (var lim=len; lim > 1; lim = (lim+1)/2){ for (var j=0,k=0; k < lim; j++, k+=2){ m=len; lim > 1; lim = (lim+1)/2){ for (var j=0,k=0; k < lim; j++, k+=2){ work[j] = merge(work[k], work[k+1]); } work[j] = []; //in case of odd work[j] = merge(work[k], work[k+1]); } work[j] = []; //in case of odd

number of items } return work[0]; }number of items } return work[0]; }

Page 19: Enhance Web Performance

Too much DOM interactionToo much DOM interaction

Reflow happens at various points in timReflow happens at various points in time: e: Initial page load.Initial page load. Browser window resize.Browser window resize. DOM nodes added or removed. (When you add or remove a DDOM nodes added or removed. (When you add or remove a D

OM node. )OM node. ) Layout styles applied. (When you apply a style dynamically (sLayout styles applied. (When you apply a style dynamically (s

uch as element.style.width="10px").) uch as element.style.width="10px").) Layout information retrieved. (When you retrieve a measureLayout information retrieved. (When you retrieve a measure

ment that must be calculated, such as accessing offsetWidth, ment that must be calculated, such as accessing offsetWidth, clientHeight, or any computed CSS value (via getComputedStclientHeight, or any computed CSS value (via getComputedStyle() in DOM-compliant browsers or currentStyle in IE), while yle() in DOM-compliant browsers or currentStyle in IE), while DOM changes are queued up to be made.)DOM changes are queued up to be made.)

Page 20: Enhance Web Performance

perform as many changes as perform as many changes as possible outside of the live possible outside of the live

DOM structure DOM structure ► for (var i=0; i < items.length; i++){ var item = document.for (var i=0; i < items.length; i++){ var item = document.

createElement("li"); item.appendChild(document.crecreateElement("li"); item.appendChild(document.createTextNode("Option " + i); list.appendChild(item); }ateTextNode("Option " + i); list.appendChild(item); }

► var fragment = document.createDocumentFravar fragment = document.createDocumentFragment(); for (var i=0; i < items.length; i++){ var igment(); for (var i=0; i < items.length; i++){ var item = document.createElement("li"); item.apptem = document.createElement("li"); item.appendChild(document.createTextNode("OptionendChild(document.createTextNode("Option " + i); fragment.appendChild(item); } list.appe " + i); fragment.appendChild(item); } list.appendChild(fragment); ndChild(fragment);

Page 21: Enhance Web Performance

remove a node from the live remove a node from the live DOM before operating on it DOM before operating on it

list.style.display = "none"; list.style.display = "none";

for (var i=0; i < items.length; i++){ for (var i=0; i < items.length; i++){ var item = document.createElement("li"); item.avar item = document.createElement("li"); item.appendChild(document.createTextNode("Option ppendChild(document.createTextNode("Option " + i);" + i);list.appendChild(item); } list.appendChild(item); }

list.style.display = ""; list.style.display = "";

Page 22: Enhance Web Performance

► change the class using JavaScript rather than change the class using JavaScript rather than applying individual style changes manually applying individual style changes manually element.style.backgroundColor = "blue"; element.style.color = "red"; eelement.style.backgroundColor = "blue"; element.style.color = "red"; element.style.fontSize = "12em"; lement.style.fontSize = "12em"; element.className = "newStyle"; element.className = "newStyle";

► cache results that you retrieve from the DOM cache results that you retrieve from the DOM document.getElementById("myDiv").style.left = document.getElementdocument.getElementById("myDiv").style.left = document.getElementById("myDiv").offsetLeft + document.getElementById("myDiv").offsetById("myDiv").offsetLeft + document.getElementById("myDiv").offsetWidth + "px"; Width + "px"; var myDiv = document.getElementById("myDiv"); myDiv.style.left = myvar myDiv = document.getElementById("myDiv"); myDiv.style.left = myDiv.offsetLeft + myDiv.offsetWidth + "px"; Div.offsetLeft + myDiv.offsetWidth + "px";

Page 23: Enhance Web Performance

Proccess the HTMLCollection tyProccess the HTMLCollection type pe

► var divs = document.getElementsByTagName("div");var divs = document.getElementsByTagName("div");for (var i=0; i < divs.length; i++){ //infinite loop document.for (var i=0; i < divs.length; i++){ //infinite loop document.body.appendChild(document.createElement("div")); } body.appendChild(document.createElement("div")); }

► var divs = document.getElementsByTagName("div"); var divs = document.getElementsByTagName("div"); for (var i=0, len=divs.length; i < len; i++){ //not an infinite for (var i=0, len=divs.length; i < len; i++){ //not an infinite loop document.body.appendChild(document.createEleloop document.body.appendChild(document.createElement("div")); }ment("div")); }

Page 24: Enhance Web Performance

Fastest way to build an HTML Fastest way to build an HTML stringstring

► String concatString concat► var arr = ['item 1', 'item 2', 'item 3', ...], list = ''; for (var i var arr = ['item 1', 'item 2', 'item 3', ...], list = ''; for (var i

= 0, l = arr.length; i < l; i++) { list += '<li>' + arr[i] + '</li>'; } = 0, l = arr.length; i < l; i++) { list += '<li>' + arr[i] + '</li>'; } list = '<ul>' + list + '</ul>';list = '<ul>' + list + '</ul>';

► Array pushingArray pushing► var arr = ['item 1', 'item 2', 'item 3', ...], list = []; for (var i var arr = ['item 1', 'item 2', 'item 3', ...], list = []; for (var i

= 0, l = arr.length; i < l; i++) { list[list.length] = '<li>' + arr[i] = 0, l = arr.length; i < l; i++) { list[list.length] = '<li>' + arr[i] + '</li>'; } list = '<ul>' + list.join('') + '</ul>';+ '</li>'; } list = '<ul>' + list.join('') + '</ul>';

► Native joinNative join► var arr = ['item 1', 'item 2', 'item 3', ...]; var list =var arr = ['item 1', 'item 2', 'item 3', ...]; var list =

'<ul><li>' + arr.join('</li><li>') + '</li></ul>'; '<ul><li>' + arr.join('</li><li>') + '</li></ul>';

Page 25: Enhance Web Performance

Javascript good practiceJavascript good practice► Always use “var” for declaration. Always use “var” for declaration. ► Feature detect rather that browser detect. Feature detect rather that browser detect. ► Use Object literal notation: Use Object literal notation:

► Var order = { Var order = { ► mode: ‘default’, mode: ‘default’, ► obj : { id:’1’, val:’10’}, obj : { id:’1’, val:’10’}, ► array1 : [‘1’, ‘2’, ‘3’], array1 : [‘1’, ‘2’, ‘3’], ► show : function(elToshow) { show : function(elToshow) { ► } } ► } }

► Use square bracket notation Use square bracket notation MyObject[“property”] rather than MyObject.property MyObject[“property”] rather than MyObject.property Use dot notation for standard properties of objects Use dot notation for standard properties of objects Square bracket notation to access properties which are defined as objeSquare bracket notation to access properties which are defined as obje

cts in the page. cts in the page. ► Good: document.forms[“formname”].elements[“input”].value Good: document.forms[“formname”].elements[“input”].value ► Bad : document.formname.inputname Bad : document.formname.inputname

Page 26: Enhance Web Performance

Javascript good practiceJavascript good practice► Avoid eval. Use JSON.parse(jsontext, reviver); Avoid eval. Use JSON.parse(jsontext, reviver); ► Use === and !== in place of == and !=. Because of type coercion. Use === and !== in place of == and !=. Because of type coercion. ► Cache variables. Cache variables. ► Falsy values in js. Falsy values in js.

If (“”), if (0), if (null), if (undefined), if(NaN) are false. If (“”), if (0), if (null), if (undefined), if(NaN) are false. ► The Unary + Operator To TypeConvert To Number The Unary + Operator To TypeConvert To Number

Eg: var input1 = document.getElementById(‘text1’).value; Eg: var input1 = document.getElementById(‘text1’).value; var input2 = document.getElementById(‘text2’).value; var input2 = document.getElementById(‘text2’).value; var value1 = (+input1)+(+input2) or var value1 = (input1-0)+(input2-0); var value1 = (+input1)+(+input2) or var value1 = (input1-0)+(input2-0);

► Avoid Cluttering The Global Namespace. Use object literals. Avoid Cluttering The Global Namespace. Use object literals. ► Avoid “with”Avoid “with”► Use JSON instead of XMLUse JSON instead of XML► Use Correct <script> TagsUse Correct <script> Tags

<script type=“text/javascript” src=”..”>, Language tag is deprecate<script type=“text/javascript” src=”..”>, Language tag is deprecated. d.

More On http://www.javascripttoolbox.com/bestpractices/

Page 27: Enhance Web Performance

Minify HTMLMinify HTML

Page 28: Enhance Web Performance

Minify HTMLMinify HTML

► Placing Inline Elements Inside Block ElementsPlacing Inline Elements Inside Block Elements► Using <strong> and <em> instead of <b> and <i> for Bolding and ItalUsing <strong> and <em> instead of <b> and <i> for Bolding and Ital

icizing icizing ► Using <del> and <ins> instead of <s> and <strike> for showing deletUsing <del> and <ins> instead of <s> and <strike> for showing delet

ed and inserting texted and inserting text► Using Less Line BreaksUsing Less Line Breaks► Avoid using inline stylingAvoid using inline styling► Inline Images data:URL scheme ---- disobedientInline Images data:URL scheme ---- disobedient

Page 29: Enhance Web Performance

Css GuidelinesCss Guidelines

Page 30: Enhance Web Performance

Css GuidelinesCss Guidelines► What’s the key selector?What’s the key selector?

a > img {//props} div > pa > img {//props} div > p► How the Style System Matches RulesHow the Style System Matches Rules

Style Computation – R to L Style Computation – R to L ► Four types of cssFour types of css

ID Rules ID Rules button#backButton { }button#backButton { } 、 、 #urlBar[type=“autocomplete”] { } tr#urlBar[type=“autocomplete”] { } treeitem > treerow > treecelleeitem > treerow > treecell 、、 #myCell:active { } #myCell:active { }

Class RulesClass Rules button.toolbarButton { }button.toolbarButton { } 、、 .fancyText { } .fancyText { } 、、 menuitem > .mmenuitem > .menu-left[checked="true"] { } enu-left[checked="true"] { }

Tag Rules Tag Rules td { }td { } 、、 treeitem > treerow { }treeitem > treerow { } 、、 input[type="checkbox"] { } input[type="checkbox"] { }

Universal Rules Universal Rules [hidden=“true”] { } [hidden=“true”] { } 、、 * { }* { } 、 、 tree > [collapsed="true"] { } tree > [collapsed="true"] { }

Page 31: Enhance Web Performance

Guidelines for Efficient CSSGuidelines for Efficient CSS

►Avoid Universal Rules!. Avoid Universal Rules!. ►Don’t qualify ID/class-categorizDon’t qualify ID/class-categoriz

ed rules with tag/class names ed rules with tag/class names BAD - butBAD - button#backButton { } GOOD - #backButton { } ton#backButton { } GOOD - #backButton { }

►Tag-categorized rules should nevTag-categorized rules should never contain a child selector! er contain a child selector! BAD - treehead BAD - treehead > treerow > treecell { } BEST - .treecell-header { } > treerow > treecell { } BEST - .treecell-header { }

►Rely on inheritance! Rely on inheritance! BAD - #bookmarkMenuItem > .mBAD - #bookmarkMenuItem > .menu-left { list-style-image: url(blah); } GOOD - #bookmarkMenuItem { list-style-image: enu-left { list-style-image: url(blah); } GOOD - #bookmarkMenuItem { list-style-image: url(blah); } url(blah); }

https://developer.mozilla.org/en/Writing_Efficient_CSS

Page 32: Enhance Web Performance

Tools of Analyzing Tools of Analyzing PerformancePerformance

► YSlow (YAHOO!)YSlow (YAHOO!)http://http://developer.yahoo.com/yslowdeveloper.yahoo.com/yslow//

► Page Speed (Google) Page Speed (Google) http://code.google.com/speed/page-speehttp://code.google.com/speed/page-speed/d/

► FirebugFirebughttp://getfirebug.com/http://getfirebug.com/

► FasterfoxFasterfoxhttp://http://fasterfox.mozdev.orgfasterfox.mozdev.org

Page 33: Enhance Web Performance

Thanks!Thanks!


Recommended