Client-side performance
Mykyta Semenistyi
Table of contents
1. Perceived performance
2. Build systems
3. JavaScript
4. Data caching
5. CSS, rendering and fonts
6. DOM
7. Frameworks tweaking
8. Image optimizations
Perceived performance
0.1s
feels instantaneously
1s
mental context switch
10s
interest in dialog loss
JAKOB NIELSEN on January 1, 1993
Content loading
might not be loaded
at once
Visual feedback
Icons by Seth Coelen http://dribbble.com/shots/1167728-PSD-CSS-Button-State-Workfiles
Instant Click
how long ago you
gave yourself away
pjax-powered
Sleeping Devices
Page Visibility API hypnos
IE10+, FF 27+, Chrome 31+, iOS 7, Android 4.4,
IEMobile 10, Safari 7+
visibilitychange
event
hidden
Build systems
Grunt Gulp Broccoli
Build systems
Optimize images Generate sprites
Convert images Concatenate css, js,html
Minify css, js,html Inline css
Compress static files ...
JS performance
“Programmers waste enormous amounts of time thinking about, or worrying
about, the speed of noncritical parts of their programs, and these attempts at
efficiency actually have a strong negative impact when debugging and
maintenance are considered. We should forget about small efficiencies, say
about 97% of the time; premature optimization is the root of all evil. Yet we
should not pass up our opportunities in that critical 3%.”
Donald Knuth, Structured Programming With go to Statements
var person = {
name: "Nicholas",
age: 30
};
function displayInfo(){
var count = 5;
with(person){
alert(name + " is " + age);
alert("Count is " + count);
}
}
displayInfo();
Execution context
Nicholas C. Zakas - Writing Efficient JavaScript: Chapter 7 - Even Faster Websites
for (var i = 0; i < theArray.length; i++) {
copyOfTheArray[i] = theArray[i];
}
var len = theArray.length;
for (var i = 0; i < len; i++) {
copyOfTheArray[i] = theArray[i];
}
With caching:
Without caching:
Loops performance
for (var i in theArray) {
copyOfTheArray[i] = theArray[i];
}
theArray.forEach(function(it, idx){
copyOfTheArray[idx] = it;
});
forEach:
for in:
Loops performance
WebWorkersBring threading to JS
UI Thread:
var worker = new Worker('task.js');
worker.addEventListener('message', function(e) {
console.log('Worker said: ', e.data);
}, false);
worker.postMessage('Hello World');
worker.terminate();
Worker:
self.addEventListener('message', function(e) {
//e.data === ‘Hello World’;
//process data
self.postMessage(result);
}, false);
self.close();
var blob = new Blob([
"onmessage = function(e) { postMessage
('msg from worker'); }"]);
// Obtain a blob URL reference to our worker
var blobURL = window.URL.createObjectURL
(blob);
var worker = new Worker(blobURL);
On fly:
Eric Bidelman http://www.html5rocks.com/en/tutorials/workers/basics/
WebWorkersPeculiarities
Dedicated Shared
available within the
creator script
available within the same
domain scripts
Workers have access to:
● The navigator object
● The location object (read-only)
● XMLHttpRequest
● setTimeout etc.
● The Application Cache
● Importing external scripts using the importScripts() method
● Spawning other web workers
Workers do NOT have access to:
● The DOM (it's not thread-safe)
● The window object
● The document object
● The parent object
Transferrable types:
● string
● JSON
● binary data (File, Blob, ArrayBuffer)
WebWorkersUse cases
Ray Tracer
Video/audio
Route
Tracer
DNA Analyzing
WebWorkers
but...
Event loop in JS UI Thread
...onclick XHR
state change
setTimeout setInterval
onclick XHR
state change
setTimeout
Long running scripts
var sum = 0;
for (var i = 0; i < 23000000; i++){
sum += Math.random() * i;
}
chunks
by count
by time
if (Date.now() - start > 100){
setTimeout(process);
} else {
process();
}
if (i % 10000 === 0){
setTimeout(process);
} else {
process();
}
asm.js
“use asm”;
JIT vs AOT
no need for dynamic type guards, boxed values, and garbage collection.
asm.js
wat...
asm.js
how to write
function strlen(ptr) {
ptr = ptr|0;
var curr = 0;
curr = ptr;
while (MEM8[curr]|0 != 0) {
curr = (curr + 1)|0;
}
return (curr - ptr)|0;
}
asm.js
why
Native code
NaCl PNaCl
executes native code securely
through Software Fault Isolation
(SFI)
1. compiling the source code to a
portable bitcode format
2. translating the bitcode to a
host-specific executable.
Data caching
Caching is tricky. Avoid it to reduce complexity, allowing
you to focus on what matters: javascript variable
minification.
@webperftips
1. someFunction(‘param’); 2. someFunction(‘param’);
results[‘param’] = result;
result
return result;
return results[‘param’];
Memoize
Util libraries: Standalone modules:
Memoize.js
Memoize
localStorage sessionStorage
Web Storage
clears when window is closed
+:
1. IE8+
2. Simple API
3. Simple sync API
-:
1. Poor performance for large data
2. Lack of indexing
3. Manual serialization
Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/
if (!localStorage.checkins) localStorage.checkins = JSON.stringify([]);
Web Storage
basket.require(
{ url: 'jquery.js' },
{ url: 'underscore.js' },
{ url: 'backbone.js' }
);
IndexedDB
Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/
+:
1. Good performance
2. Async API
3. Search is indexed
4. Transactions
-:
1. IE10+
2. Complex API
var request = indexedDB.open("geomood", version);
request.onupgradeneeded = function(event) {}
request.onsuccess = function(event) {}
IndexedDB
WebSQL
+:
1. Mobile support
2. Good performance
3. Async API
4. Search is indexed
5. Transactions
-:
1. Deprecated (IE and FF)
2. Requires knowledge of SQL
3. SQL
Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/
WebSQL
Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/
this.db = openDatabase('geomood', '1.0', 'Geo-Mood Checkins', 8192);
this.db.transaction(function(tx) {
tx.executeSql("create table if not exists " +
"checkins(id integer primary key asc, time integer, latitude float," +
"longitude float, mood string)",
[],
function() { console.log("success"); }
);
});
WebSQL
localForage
WebSQL IndexedDB
localStorage-like API
localforage.setItem('key', 'value', doSomethingElse);
CSS, fonts, rendering
Larger font sizes cost significantly more across the wire. For
quick web font loading, keep them under 10pt.
@webperftips
CSS Frameworks
~98 kB ~146 kB
~ 90% of the CSS rules are unused
grunt-uncss
CSS selectors
Ben Frain http://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/
1. Data attribute
2. Data attribute (qualified)
3. Data attribute (unqualified but with value)
4. Data attribute (qualified with value)
5. Multiple data attributes (qualified with values)
6. Solo pseudo selector (e.g. :after)
7. Combined classes (e.g. class1.class2)
8. Multiple classes
9. Multiple classes with child selector
10. Partial attribute matching (e.g. [class^=“wrap”])
11. nth-child selector
12. nth-child selector followed by another nth-child
selector
13. Insanity selection (all selections qualified, every class
used e.g. div.wrapper > div.tagDiv > div.tagDiv.layer2
> ul.tagUL > li.tagLi > b.tagB > a.TagA.link)
14. Slight insanity selection (e.g. .tagLi .tagB a.TagA.link)
15. Universal selector
16. Element single
17. Element double
18. Element treble
19. Element treble with pseudo
20. Single class
Test Chrome 34 Firefox 29 Opera 19 IE9 Android 4
1 56.8 125.4 63.6 152.6 1455.2
2 55.4 128.4 61.4 141 1404.6
3 55 125.6 61.8 152.4 1363.4
4 54.8 129 63.2 147.4 1421.2
5 55.4 124.4 63.2 147.4 1411.2
6 60.6 138 58.4 162 1500.4
7 51.2 126.6 56.8 147.8 1453.8
8 48.8 127.4 56.2 150.2 1398.8
... ... ...
... ... ...
Biggest Diff. 16 13.6 17.6 31 152
Slowest 13 6 13 10 6
Dynamic CSS
● dynamic properties
● media-queries
● key-frames animations
veinjs
vein.inject([{
'@media (max-width: 768px)': ['h2']
}], {
'color': '#f00'
});
vein.inject(
['h2', 'h3'],
{'color' : 'green', 'font-weight' : null}
);
Dynamic CSS
why
Layout performance
this block is being
repainted on each
css change
Layout performance
layers
● -webkit-transform: translateZ(0)
● -webkit-transform: translate3d
(0,0,0);
● backface-visibility: hidden
GPU Acceleration
New Layer
● not enough VRAM
● slow CPU to GPU transfer
Layout performance
layers
Pitfalls:
Reflow
geometrical calculations of layout
el:
clientHeight
clientLeft
focus()
getBoundingClientRect()
getClientRects()
innerText
offsetHeight
offsetWidth
outerText
scrollTop
scrollWidth
window:
getComputedStyle()
scrollBy()
scrollTo()
scrollX
scrollY
webkitConvertPointFromN
odeToPage()
webkitConvertPointFromP
ageToNode()
Layout performance
summary
● Try to localize
changes
● Try to batch changes FastDOM
● window.requestAnimationFrame
● disable animations when possible
● don’t cause reflow
Fonts loadtime
1. Load only fonts you need
2. Load only charsets you need
3. Font Load Events API
Ilya Grigorik http://www.igvita.com/2014/01/31/optimizing-web-font-rendering-performance/
var font = new FontFace("FontA",
"url(http://mysite.com/fonts/fontA.woff)", {});
font.ready().then(function() {
// font loaded.. swap in the text / define own behavior.
});
font.load(); // initiate immediate fetch / don't block on render tree!
DOM
Inserting <br> elements liberally throughout your markup will
give the rendering engine enough breaks to stay fast for the
whole day.
@webperftips
<!doctype html>
<html lang="en">
<head>
...
<link rel="stylesheet" href="">
</head>
<body>
...
<script type=“text/javascript” src=""></script>
</body>
</html>
in the head to get styling asap
in the bottom of the body
non-blocking
async
defer
Document parsing
Text editing
innerHTML innerText textContent
html parsing layout reflow bingo! IE9+
Frameworks
Instead of doing costly ajax calls to a server for data, simply
generate random data on the client side
and use that instead.
@webperftips
you might not need jQuery
IE8+
$(‘selector’) document.querySelectorAll(‘selector’)
$.ajax new XMLHttpRequest()
.animate() CSS3 Animations
.addClass() .classList.add()
.html() .innerHTML
...
jQuery-free frameworks
React vue.js
MVVM
ultra-fast
~13 kb gzipped
widget-oriented
fast
virtualDOM
Backbone
grunt-contrib-jst
Jquery-less
document.fragment
Image optimizations
Sprites
Icons by Denis http://www.iconarchive.com/show/cat-commerce-icons-by-iconka.html
add.png client.png mail.png search.png trash.png
sprite.png
Sprites
.sprite-add-icon { background-position: 0 0; width: 128px; height: 128px; }
.sprite-client-icon { background-position: -178px 0; width: 128px; height: 128px; }
.sprite-mail-icon { background-position: -356px 0; width: 128px; height: 128px; }
.sprite-search-icon { background-position: -534px 0; width: 128px; height: 128px; }
.sprite-trash-icon { background-position: -712px 0; width: 128px; height: 128px; }
css snippets
Inline images
<img src="data:image/jpg;base64,
/9j/4AAQSkZJRgABAQEAYABgAAD/2w……
…….. />
background-image: url('data:image/jpg;
base64,
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDA
AcF……..’)
+:
1. One request
2. IE7+
-:
1. base64 > image size
2. not cached itself
3. processor time
Inline images
Peter McLachlan http://www.mobify.com/blog/base64-does-not-impact-data-uri-performance/
Inline images vs sprites
Peter McLachlan http://www.mobify.com/blog/css-sprites-vs-data-uris-which-is-faster-on-mobile/
Serving perfect sized images
1. Scaling the size down with css (e.g. 50%) 2. Serving bad/small images on Retina
problem
Serving perfect sized images
solutions
media-queries srcset
( (min-device-pixel-ratio: 1.5) and (min-width: 20.001em) and
(max-width: 35.999em) ) or
( (max-device-pixel-ratio: 1.5) and (min-width: 120.001em) )
or
( (min-device-pixel-ratio: 1.5) and (min-width: 60.001em) )
IE9+, FF 23+, Chrome 31+, iOS 3.2, Android 2.1,
IEMobile 10, Safari 7+
<img src="small.jpg"
srcset="large.jpg 1024w,
medium.jpg 640w,
small.jpg 320w"
sizes="(min-width: 36)
33.3%, 100%"
/>
Chrome 33+, FF 27+, Safari 7+
Font icons
Font icons
icnfnt Fontello IcoMoon
custom builds
Compression
lossy lossless
strip metadata
group
color quantization
OptiPNG
pngquant
jpegtran
gifsicle
New, optimized formats
➔ webp
25% less size
Chrome 9+ (stable 23+), Opera 12.1+, Android 4.0+
➔ jpeg-xr
... less size
IE9+
➔ mozjpeg
work in progress
jpeg compressor
New, optimized formats
Nicholas Doyle http://calendar.perfplanet.com/2013/browser-specific-image-formats/
Convertion tools
Probably the most universal tool. Any kind of convertion,
lossless and lossy compression
webp cross-platform codec
ImageMagick
webp
jpegxr cross-platform codec
bmp -> jpegxr
jxrlib
Conditional serving
webp-detect
connect-image-optimus
koa-image-optimus
apache
nginx
varnish
iis
Accepts webp
webp on disk
1
add Vary:Accept
1
UA accepts
jpegxr
jpegxr on disk
1
0
Web Performance Part 4  "Client-side performance"

Web Performance Part 4 "Client-side performance"

  • 1.
  • 2.
    Table of contents 1.Perceived performance 2. Build systems 3. JavaScript 4. Data caching 5. CSS, rendering and fonts 6. DOM 7. Frameworks tweaking 8. Image optimizations
  • 3.
    Perceived performance 0.1s feels instantaneously 1s mentalcontext switch 10s interest in dialog loss JAKOB NIELSEN on January 1, 1993
  • 4.
    Content loading might notbe loaded at once
  • 5.
    Visual feedback Icons bySeth Coelen http://dribbble.com/shots/1167728-PSD-CSS-Button-State-Workfiles
  • 6.
    Instant Click how longago you gave yourself away pjax-powered
  • 7.
    Sleeping Devices Page VisibilityAPI hypnos IE10+, FF 27+, Chrome 31+, iOS 7, Android 4.4, IEMobile 10, Safari 7+ visibilitychange event hidden
  • 8.
  • 9.
    Build systems Optimize imagesGenerate sprites Convert images Concatenate css, js,html Minify css, js,html Inline css Compress static files ...
  • 10.
    JS performance “Programmers wasteenormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time; premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.” Donald Knuth, Structured Programming With go to Statements
  • 11.
    var person ={ name: "Nicholas", age: 30 }; function displayInfo(){ var count = 5; with(person){ alert(name + " is " + age); alert("Count is " + count); } } displayInfo(); Execution context Nicholas C. Zakas - Writing Efficient JavaScript: Chapter 7 - Even Faster Websites
  • 12.
    for (var i= 0; i < theArray.length; i++) { copyOfTheArray[i] = theArray[i]; } var len = theArray.length; for (var i = 0; i < len; i++) { copyOfTheArray[i] = theArray[i]; } With caching: Without caching: Loops performance
  • 13.
    for (var iin theArray) { copyOfTheArray[i] = theArray[i]; } theArray.forEach(function(it, idx){ copyOfTheArray[idx] = it; }); forEach: for in: Loops performance
  • 14.
    WebWorkersBring threading toJS UI Thread: var worker = new Worker('task.js'); worker.addEventListener('message', function(e) { console.log('Worker said: ', e.data); }, false); worker.postMessage('Hello World'); worker.terminate(); Worker: self.addEventListener('message', function(e) { //e.data === ‘Hello World’; //process data self.postMessage(result); }, false); self.close(); var blob = new Blob([ "onmessage = function(e) { postMessage ('msg from worker'); }"]); // Obtain a blob URL reference to our worker var blobURL = window.URL.createObjectURL (blob); var worker = new Worker(blobURL); On fly: Eric Bidelman http://www.html5rocks.com/en/tutorials/workers/basics/
  • 15.
    WebWorkersPeculiarities Dedicated Shared available withinthe creator script available within the same domain scripts Workers have access to: ● The navigator object ● The location object (read-only) ● XMLHttpRequest ● setTimeout etc. ● The Application Cache ● Importing external scripts using the importScripts() method ● Spawning other web workers Workers do NOT have access to: ● The DOM (it's not thread-safe) ● The window object ● The document object ● The parent object Transferrable types: ● string ● JSON ● binary data (File, Blob, ArrayBuffer)
  • 16.
  • 17.
  • 18.
    Event loop inJS UI Thread ...onclick XHR state change setTimeout setInterval onclick XHR state change setTimeout
  • 19.
    Long running scripts varsum = 0; for (var i = 0; i < 23000000; i++){ sum += Math.random() * i; } chunks by count by time if (Date.now() - start > 100){ setTimeout(process); } else { process(); } if (i % 10000 === 0){ setTimeout(process); } else { process(); }
  • 20.
    asm.js “use asm”; JIT vsAOT no need for dynamic type guards, boxed values, and garbage collection.
  • 21.
  • 22.
    asm.js how to write functionstrlen(ptr) { ptr = ptr|0; var curr = 0; curr = ptr; while (MEM8[curr]|0 != 0) { curr = (curr + 1)|0; } return (curr - ptr)|0; }
  • 23.
  • 24.
    Native code NaCl PNaCl executesnative code securely through Software Fault Isolation (SFI) 1. compiling the source code to a portable bitcode format 2. translating the bitcode to a host-specific executable.
  • 25.
    Data caching Caching istricky. Avoid it to reduce complexity, allowing you to focus on what matters: javascript variable minification. @webperftips
  • 26.
    1. someFunction(‘param’); 2.someFunction(‘param’); results[‘param’] = result; result return result; return results[‘param’]; Memoize
  • 27.
    Util libraries: Standalonemodules: Memoize.js Memoize
  • 28.
    localStorage sessionStorage Web Storage clearswhen window is closed +: 1. IE8+ 2. Simple API 3. Simple sync API -: 1. Poor performance for large data 2. Lack of indexing 3. Manual serialization Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/ if (!localStorage.checkins) localStorage.checkins = JSON.stringify([]);
  • 29.
  • 30.
    basket.require( { url: 'jquery.js'}, { url: 'underscore.js' }, { url: 'backbone.js' } );
  • 31.
    IndexedDB Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/ +: 1.Good performance 2. Async API 3. Search is indexed 4. Transactions -: 1. IE10+ 2. Complex API var request = indexedDB.open("geomood", version); request.onupgradeneeded = function(event) {} request.onsuccess = function(event) {}
  • 32.
  • 33.
    WebSQL +: 1. Mobile support 2.Good performance 3. Async API 4. Search is indexed 5. Transactions -: 1. Deprecated (IE and FF) 2. Requires knowledge of SQL 3. SQL Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/
  • 34.
    WebSQL Michael Mahemoff http://www.html5rocks.com/en/tutorials/offline/storage/ this.db= openDatabase('geomood', '1.0', 'Geo-Mood Checkins', 8192); this.db.transaction(function(tx) { tx.executeSql("create table if not exists " + "checkins(id integer primary key asc, time integer, latitude float," + "longitude float, mood string)", [], function() { console.log("success"); } ); });
  • 35.
  • 36.
  • 37.
    CSS, fonts, rendering Largerfont sizes cost significantly more across the wire. For quick web font loading, keep them under 10pt. @webperftips
  • 38.
    CSS Frameworks ~98 kB~146 kB ~ 90% of the CSS rules are unused grunt-uncss
  • 39.
    CSS selectors Ben Frainhttp://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/ 1. Data attribute 2. Data attribute (qualified) 3. Data attribute (unqualified but with value) 4. Data attribute (qualified with value) 5. Multiple data attributes (qualified with values) 6. Solo pseudo selector (e.g. :after) 7. Combined classes (e.g. class1.class2) 8. Multiple classes 9. Multiple classes with child selector 10. Partial attribute matching (e.g. [class^=“wrap”]) 11. nth-child selector 12. nth-child selector followed by another nth-child selector 13. Insanity selection (all selections qualified, every class used e.g. div.wrapper > div.tagDiv > div.tagDiv.layer2 > ul.tagUL > li.tagLi > b.tagB > a.TagA.link) 14. Slight insanity selection (e.g. .tagLi .tagB a.TagA.link) 15. Universal selector 16. Element single 17. Element double 18. Element treble 19. Element treble with pseudo 20. Single class Test Chrome 34 Firefox 29 Opera 19 IE9 Android 4 1 56.8 125.4 63.6 152.6 1455.2 2 55.4 128.4 61.4 141 1404.6 3 55 125.6 61.8 152.4 1363.4 4 54.8 129 63.2 147.4 1421.2 5 55.4 124.4 63.2 147.4 1411.2 6 60.6 138 58.4 162 1500.4 7 51.2 126.6 56.8 147.8 1453.8 8 48.8 127.4 56.2 150.2 1398.8 ... ... ... ... ... ... Biggest Diff. 16 13.6 17.6 31 152 Slowest 13 6 13 10 6
  • 40.
    Dynamic CSS ● dynamicproperties ● media-queries ● key-frames animations veinjs vein.inject([{ '@media (max-width: 768px)': ['h2'] }], { 'color': '#f00' }); vein.inject( ['h2', 'h3'], {'color' : 'green', 'font-weight' : null} );
  • 41.
  • 42.
    Layout performance this blockis being repainted on each css change
  • 43.
    Layout performance layers ● -webkit-transform:translateZ(0) ● -webkit-transform: translate3d (0,0,0); ● backface-visibility: hidden GPU Acceleration New Layer
  • 44.
    ● not enoughVRAM ● slow CPU to GPU transfer Layout performance layers Pitfalls:
  • 45.
    Reflow geometrical calculations oflayout el: clientHeight clientLeft focus() getBoundingClientRect() getClientRects() innerText offsetHeight offsetWidth outerText scrollTop scrollWidth window: getComputedStyle() scrollBy() scrollTo() scrollX scrollY webkitConvertPointFromN odeToPage() webkitConvertPointFromP ageToNode()
  • 46.
    Layout performance summary ● Tryto localize changes ● Try to batch changes FastDOM ● window.requestAnimationFrame ● disable animations when possible ● don’t cause reflow
  • 47.
    Fonts loadtime 1. Loadonly fonts you need 2. Load only charsets you need 3. Font Load Events API Ilya Grigorik http://www.igvita.com/2014/01/31/optimizing-web-font-rendering-performance/ var font = new FontFace("FontA", "url(http://mysite.com/fonts/fontA.woff)", {}); font.ready().then(function() { // font loaded.. swap in the text / define own behavior. }); font.load(); // initiate immediate fetch / don't block on render tree!
  • 48.
    DOM Inserting <br> elementsliberally throughout your markup will give the rendering engine enough breaks to stay fast for the whole day. @webperftips
  • 49.
    <!doctype html> <html lang="en"> <head> ... <linkrel="stylesheet" href=""> </head> <body> ... <script type=“text/javascript” src=""></script> </body> </html> in the head to get styling asap in the bottom of the body non-blocking async defer Document parsing
  • 50.
    Text editing innerHTML innerTexttextContent html parsing layout reflow bingo! IE9+
  • 51.
    Frameworks Instead of doingcostly ajax calls to a server for data, simply generate random data on the client side and use that instead. @webperftips
  • 52.
    you might notneed jQuery IE8+ $(‘selector’) document.querySelectorAll(‘selector’) $.ajax new XMLHttpRequest() .animate() CSS3 Animations .addClass() .classList.add() .html() .innerHTML ...
  • 53.
    jQuery-free frameworks React vue.js MVVM ultra-fast ~13kb gzipped widget-oriented fast virtualDOM
  • 54.
  • 55.
  • 56.
    Sprites Icons by Denishttp://www.iconarchive.com/show/cat-commerce-icons-by-iconka.html add.png client.png mail.png search.png trash.png sprite.png
  • 57.
    Sprites .sprite-add-icon { background-position:0 0; width: 128px; height: 128px; } .sprite-client-icon { background-position: -178px 0; width: 128px; height: 128px; } .sprite-mail-icon { background-position: -356px 0; width: 128px; height: 128px; } .sprite-search-icon { background-position: -534px 0; width: 128px; height: 128px; } .sprite-trash-icon { background-position: -712px 0; width: 128px; height: 128px; } css snippets
  • 58.
    Inline images <img src="data:image/jpg;base64, /9j/4AAQSkZJRgABAQEAYABgAAD/2w…… ……../> background-image: url('data:image/jpg; base64, /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDA AcF……..’) +: 1. One request 2. IE7+ -: 1. base64 > image size 2. not cached itself 3. processor time
  • 59.
    Inline images Peter McLachlanhttp://www.mobify.com/blog/base64-does-not-impact-data-uri-performance/
  • 60.
    Inline images vssprites Peter McLachlan http://www.mobify.com/blog/css-sprites-vs-data-uris-which-is-faster-on-mobile/
  • 61.
    Serving perfect sizedimages 1. Scaling the size down with css (e.g. 50%) 2. Serving bad/small images on Retina problem
  • 62.
    Serving perfect sizedimages solutions media-queries srcset ( (min-device-pixel-ratio: 1.5) and (min-width: 20.001em) and (max-width: 35.999em) ) or ( (max-device-pixel-ratio: 1.5) and (min-width: 120.001em) ) or ( (min-device-pixel-ratio: 1.5) and (min-width: 60.001em) ) IE9+, FF 23+, Chrome 31+, iOS 3.2, Android 2.1, IEMobile 10, Safari 7+ <img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36) 33.3%, 100%" /> Chrome 33+, FF 27+, Safari 7+
  • 63.
  • 64.
    Font icons icnfnt FontelloIcoMoon custom builds
  • 65.
    Compression lossy lossless strip metadata group colorquantization OptiPNG pngquant jpegtran gifsicle
  • 66.
    New, optimized formats ➔webp 25% less size Chrome 9+ (stable 23+), Opera 12.1+, Android 4.0+ ➔ jpeg-xr ... less size IE9+ ➔ mozjpeg work in progress jpeg compressor
  • 67.
    New, optimized formats NicholasDoyle http://calendar.perfplanet.com/2013/browser-specific-image-formats/
  • 68.
    Convertion tools Probably themost universal tool. Any kind of convertion, lossless and lossy compression webp cross-platform codec ImageMagick webp jpegxr cross-platform codec bmp -> jpegxr jxrlib
  • 69.