JavaScript front end performance optimizations

Preview:

Citation preview

JavaScript Front-End Performance Optimizations

Northeast JavaScript Conference

LOVE2DEV.COM

My BioMicrosoft MVPASP Insider Edge User AgentWeb Developer 25 yearsAuthor & Speaker

@ChrisLoveLove2Dev.com

Source Codehttp://

GitHub.com/docluv

Slide Deck http://slideshare.net/docluv/presentations

10 Days to HTML5 Fitness

http://bit.ly/2ctJMiU

Annoying???

LOVE2DEV.COM

"Also take a step back for a minute and consider the intent of this change: a faster web is great for everyone, but especially for users. Lots of websites have demonstrated that speeding up the user experience results in more usage. So speeding up your website isn’t just something that can affect your search rankings–it’s a fantastic idea for your users.“

http://bit.ly/SPPB4k

Matt Cutts

LOVE2DEV.COM

GOALSWeb Trends & Some HistoryFront-End Architecture Best PracticesCoding SyntaxNavigation & Performance Timing APIBuild & Deploy

Web Trends & History

LOVE2DEV.COM

6 Years of JS Weight Gain

The Reach of JavaScript ExpandedWeb Applications/SPAs

HTML5 GamesBasic Web Pages

JavaScript Execution Speed

DOM InteractionsAccelerated Graphics

Page Load Time

Conference Sponsor Sites Performance

LOVE2DEV.COM

Conference Sponsor Sites Averages

LOVE2DEV.COM

•Document Complete 6.94s• Fully Loaded 8.7s• Page Weight 2.8MB• JS Weight 788kb

Web Sites Are Obese & Out of Shape

http://httpArchive.org as of 5/15/2016

117 File Requests – 2.4+MB23 JavaScript Files - 401KB7.1 CSS Files – 74KB56 Images – 1.577MB36 TCP Connections19 Domains48% Cacheable

Is JavaScript the Problem?

YUI

  TotalSize (k)

NumberElements

CSSRules

ImageFiles

ScriptLines (F)

ScriptLibraries

Site #1 3,697 1,504 1,392 41 77,768

Site #2 2,278 1,100 5,325 29 39,183

Site #3 1,061 2,673 1,105 66 12,643

Site #4 1,812 4,252 1,672 12 10,284

Site #5 1,372 900 3,902 6 38,269

jQuery Prototype ExtJS OtherScriptaculous

YUI

  TotalSize (k)

NumberElements

CSSRules

ImageFiles

ScriptLines (F)

ScriptLibraries

Site #1 3,697 1,504 1,392 41 77,768

Site #2 2,278 1,100 5,325 29 39,183

Site #3 1,061 2,673 1,105 66 12,643

Site #4 1,812 4,252 1,672 12 10,284

Site #5 1,372 900 3,902 6 38,269

jQuery Prototype ExtJS OtherScriptaculous

Fastest

YUI

  TotalSize (k)

NumberElements

CSSRules

ImageFiles

ScriptLines (F)

ScriptLibraries

Site #1 3,697 1,504 1,392 41 77,768

Site #2 2,278 1,100 5,325 29 39,183

Site #3 1,061 2,673 1,105 66 12,643

Site #4 1,812 4,252 1,672 12 10,284

Site #5 1,372 900 3,902 6 38,269

jQuery Prototype ExtJS OtherScriptaculous

Slowest

Is JavaScript the Problem?• Bytes Must Be Downloaded• Bytes Cost Real Money• 25% of US Exceeds Monthly Bandwidth

• Bytes Take Time• Scripts Must Be Evaluated• Libraries Can Overwrite Native APIs or Don’t Use Native APIs

LOVE2DEV.COM

Don’t Guess•Use Profiling Tools• Establish Benchmarks• < 1s Desktop/Broadband• < 3s Mobile/GPRS

• Test On Real Devices Against ‘Real Site’• Have a 2G Day

• Apply Scientific Method to Solve Problems

LOVE2DEV.COM

Establish a Performance Culture

• Make Perforamance a 1st Class Citizen of Your Team• Include Developers, Architects, QA &

Stakeholders• Etsy Quarterly Performance Reports

• https://codeascraft.com/2016/04/28/q1-2016-site-performance-report/

• Designing For Performance• http://amzn.to/2d30GRy

Don’t Assume Broadband

What Does Your Site Cost?

http://whatdoesmysitecost.com

Power Consumption

Real & Perceived Performance

Architecture Best Practices

LOVE2DEV.COM

Place Script References At The Bottom• SCRIPT is a Blocking Action• Allow Browser to Render As Much As Possible Before Evaluating & Executing Scripts

JS Parse & Execution Time• Scripts Must Be Downloaded• Scripts Must Be Evaluated•Majority of Traffic from Mobile Class Devices• Lower Powered CPU• Less Memory

• Etsy Tool• https://timkadlec.com/2014/09/js-parse-and-execution-time/

Best Practice• Ask If Script/Library/Framework Is Really Needed• Are Their Alternatives?• Strive to Use Libraries Components That Do What Needs to be Done

Best Practice – Libraries & Frameworks•Use A Single Library• Keep Library Up To Date• Avoid Duplicate References• Avoid Duplicate Versions

Avoid Duplicate Code<html><head><title>Test</title></head><body>…<script src="jquery.js" … ></script><script src="myscript.js" … ></script> <script src="navigation.js" … ></script><script src="jquery.js" … ></script></body>

</html>

Avoid Duplicate Code

52%of the pages on the web

have duplicate code

Standardize on Single Library/Framework<script src="jquery.js" … ></script><script src="prototype.js" … ></script><script src="dojo.js" … ></script><script src="animater.js" … ></script><script src="extjs.js" … ></script><script src="yahooui.js" … ></script><script src="mochikit.js" … ></script><script src="lightbox.js" … ></script><script src="jslibs.js" … ></script><script src=“gsel.js" … ></script>…

ASP.NET Web Client Library

Prototype

jQuery/jQueryUI

Ember

Angular

React

Ask If It Is Needed• Avoid Framework Archeology•Don’t Use a Library/Framework to be Cool • Resume Driven Development

• Remember the Goal is to Make the Customer Happy• They Pay the Bills!

•Majority of Pages/Sites are Still Read-Only

Use Async & Defer• Allows Browser to Finish Rendering Cycle•Use When Script Order is not important•Use When Script is not needed to render

Audit 3rd Parties

3rd Parties•Often Added By Marketing Departments•Use of Tag Managers•Many Are Not Used by Stakeholders•Not Part of Application/Site Q/A•Not Managed By DevOps•Not Held to SLA

LOVE2DEV.COM

3rd Parties• You Are Outsourcing Control Of Your Business To A Supplier You Have Little or No Control• They Can & Do Have A Big Impact On Your Brand Image and Engagment

LOVE2DEV.COM

DOM Interactions• Built In DOM Methods More Efficient• Avoid Type Conversion• Avoid DOM Chatiness

LOVE2DEV.COM

DOM Methods More Efficient• querySelector• querySelectorAll• firstElementChild• nextElementSibling• previousElementSibling• lastElementChild• childElementCount

LOVE2DEV.COM

function InsertUsername(){

document.getElementById('user').innerHTML = userName;}

User .innerHTML to Construct Your PageUse DOM Efficiently

function InsertUsername(){

document.getElementById('user').innerHTML = userName;}

User .innerHTML to Construct Your PageUse DOM Efficiently

function BuildUI() { var elm = document.getElementById('ui'); var contents = BuildTitle() + BuildBody() + BuildFooter(); elm.innerHTML = contents;}

Batch Markup ChangesUse DOM Efficiently

function BuildUI() { var elm = document.getElementById('ui'); var contents = BuildTitle() + BuildBody() + BuildFooter(); elm.innerHTML = contents;}

Batch Markup ChangesUse DOM Efficiently

function BuildUI() { var elm = document.getElementById('ui'); var contents = BuildTitle() + BuildBody() + BuildFooter(); elm.innerHTML = contents;}

Batch Markup ChangesUse DOM Efficiently

function BuildUI() { var elm = document.getElementById('ui'); var contents = BuildTitle() + BuildBody() + BuildFooter(); elm.innerHTML = contents;}

Batch Markup ChangesUse DOM Efficiently

Small Healthy DOM

LOVE2DEV.COM

Use DOM Methods to Create Collections

LOVE2DEV.COM

Use DOM Selectors Collection Access

LOVE2DEV.COM

Avoid DOM Type Conversion

Avoid DOM Chatiness

Performance•UI Responsiveness• Identify CPU Intensive Code• Identify Frame Rate Issues

• JavaScript Profiling• Identify Code Bottlenecks

LOVE2DEV.COM

Memory Profiling

Memory Profiling• Timeline to Identify Memory Pressure Issues• Track Down Memory Leaks

LOVE2DEV.COM

Memory Utilization

Memory Leaks

Memory Leaks

Memory Leaks

Array Best Practices• Pre-Allocate• Keep Array Type Consistent•Use Typed Arrays• Keep Arrays Dense• Enumerate Efficiently

LOVE2DEV.COM

Use Typed Arrays

LOVE2DEV.COM

Sparse vs Dense Arrays• Arrays are Sparse, they have holes in them• A map from indices to values

LOVE2DEV.COM

Sparse vs Dense Arraysvar a = new Array(3);

a [ , , ];

a.length === 3 a[0] === undefined

a.map(function (x, i) { return i }) === [ , , ]

LOVE2DEV.COM

Sparse vs Dense Arrays• Array(undefined, undefined, undefined)

• a.map(function (x, i) { return i }) === [ 0, 1, 2 ]

LOVE2DEV.COM

Keep Arrays Dense

LOVE2DEV.COM

Enumerate Arrays Efficently

LOVE2DEV.COM

Don’t do useless work

setInterval(draw, 0);setTimeout(draw, 0);requestAnimationFrame(draw);setTimeout(draw, 1000 / 60);

Do avoid chattiness with the DOM

JavaScript

DOM

for (var i = 0; i < this.nOfBubbles; i++) { document.body.box.getElementById("ball0").style.left = b.x + "px"; document.body.box.getElementById("ball0").style.top = b.y + "px";}

Do check types of values from DOMthis.nOfBubbles =

document.getElementById(“dropDown").value;

30%of rendering time in string conversion

Slow Operations

11%Value

Conversions 18%

GC 17%

Your Code 45%

JavaScript: Flexibility or performance

Flexibility Performance

“Think C++”“Think Script”

Simple Websites Complex Apps, Games

var r = 3 * "10"; // r == 300

var a = new Array();a.push(10);

var p = {x: 0, y: 0};p.z = 5;p["some text"] = 1;p[1] = 2;eval("var s = p[1] * a[0]"); // s == 20

var r = 3 * parseInt("10");

var a = new Array(100);a[0] = 10;

var p = new Point(0, 0, 0);p.z = 5;

• C, C++, C# (Static Language)

• static int DoMath(int value) {• int result = 0;• for (int i = 0; i < 10000; i++) {

• for (int j = 0; j < 10000; j++) {

• result = i + j + value;

• }• }• return result;• }

JavaScript (Dynamic Language)function DoMath(value) { for (var i = 0; i < 10000; i++) { for (var j = 0; j < 10000; j++) { var result = i + j + value; } } return result;}

Stick to Integer MathWrite Fast JavaScript

Stick to Integer MathWrite Fast JavaScript

C++ JavaScriptDoMath(999);

40ms200ms (~5x)

DoMath(999/2);40ms

1600ms (~40x)

Stick to Integer MathWrite Fast JavaScript

0x005e22a0Pointer01 Type Tag449.4999999……… Value

02 Type Tag

“Hello World”Value

0x005e4148Pointer

Stick to Integer MathWrite Fast JavaScript

DoMath(Math.floor(999 / 2));

var b = Math.ceil((p[i].r + p[i].g + p[i].b) / 3);

Stick to Integer MathWrite Fast JavaScript

DoMath(Math.floor(999 / 2));

var b = Math.ceil((p[i].r + p[i].g + p[i].b) / 3);

Stick to Integer MathWrite Fast JavaScript

DoMath(Math.floor(999 / 2));

var b = Math.ceil((p[i].r + p[i].g + p[i].b) / 3);

Do write fast objects Add all properties in constructor Don’t delete properties Use identifiers for property names Use getters and setters sparingly Avoid conditionally adding properties Avoid default property values on prototype objects

Navigation & Performance Timing APIs Give You Access to Real Times Various Stages of Document Lifecycle

https://developer.mozilla.org/en-US/docs/Web/API/Navigation_timing_API http://www.html5rocks.com/en/tutorials/webperformance/basics/

Navigation & Performance Timing APIs

How to Build JavaScript Maintain Development, QA, Production Versions Use a Build Tool

Grunt, Gulp, WebPac, Broccoli, Node, etc

How to Build Production JavaScript Bundle & Minify

A Single Request is much faster to download and parse Compress

Gzip Content-Encoding Header

Set Proper Cache Headers CacheControl: "public, max-age=31449600, s-max-age=360“

Use A CDN Host on Static Server

How to Build Production JavaScript Node Modules Exists to Automate All these Requirements

Set it and Forget It!

Recommended