2. HTML5: Building For a Faster Web
Performance Features Tools
Eric Bidelman - Google
Google DevFest - Buenos Aires, Argentina
Nov 2, 2010
Tuesday, November 2, 2010 2
3. Agenda
• Performance Wins
• Web Storage APIs
• Web Workers & Web Sockets
• Tools & Resources
• Compatibility
3
@googledevlatam #devfest10
Tuesday, November 2, 2010 3
4. Eric Bidelman (@ebidel)
• University of Michigan, BSE Computer &
Electrical Engineering
• Developer Programs Engineer, Google
• Docs / Sites / Health / Base / OAuth /
Chrome / HTML5
4
@googledevlatam #devfest10
Tuesday, November 2, 2010 4
5. Performance
5
@googledevlatam #devfest10
Tuesday, November 2, 2010 5
6. Don’t Underestimate CSS3!
• Rounded corners, box shadows, reflection, rotations, alpha, css masks
• CSS animations & transitions
div.box {
left: 40px;
-webkit-transition: left 0.3s ease-out;
-moz-transition: left 0.3s ease-out;
-o-transition: left 0.3s ease-out;
}
div.box.totheleft { left: 0px; }
div.box.totheright { left: 80px; }
• 3D transforms trigger HW compositing in the GPU
-webkit-transform: translate3d(10px, 0, 0);
• pseudo-selectors are your friend ( :hover, :active, :valid, :invalid, :focus, :empty )
• Web Fonts
6
@googledevlatam #devfest10
Tuesday, November 2, 2010 6
7. Go Native!
• Use native methods ( not libraries )
JSON.parse(); JSON.stringify();
‘ too much padding ‘.trim();
• Query, don’t walk the DOM!
document.querySelector(‘#links’);
document.querySelectorAll(‘.myclass > span’);
• Data URIs: Render, don’t download
canvas.toDataURL();
7
@googledevlatam #devfest10
Tuesday, November 2, 2010 7
8. Go Native!
<div id="main" class="shadow rounded"></div>
var cl = document.querySelector('#main').classList;
for(var i = 0, c; c = cl[i]; ++i) {
console.log(c);
}
cl.add('highlight');
cl.remove('shadow');
cl.toggle('highlight');
cl.contains('shadow') == false
// cl.toString() == el.className
8
@googledevlatam #devfest10
Tuesday, November 2, 2010 8
9. JavaScript 1.6
• Array iterative methods: map(), filter(), forEach(),
every(), some()
[5,6,7,8].map(function(value){ // [50,60,70,80]
return value * 10;
});
// Return a new array of all mathematical constants under 2
[3.14, 2.718, 1.618].filter(function(number){
return number < 2;
});
// [1.618]
['html5','css3','webgl'].forEach(function(value){
// use value
});
• Array item location methods: indexOf(‘html5’),
lastIndexOf(‘webgl’)
9
@googledevlatam #devfest10
Tuesday, November 2, 2010 9
10. HTML5 Markup
( for web apps )
10
@googledevlatam #devfest10
Tuesday, November 2, 2010 10
11. REL Attributes
rel=”pingback”
• enables reverse linking
• automatically notify original blog when sites link to it
rel=”prefetch”
• hint for the browser that the resource is likely to be
used
11
@googledevlatam #devfest10
Tuesday, November 2, 2010 11
12. REL Attributes
rel=”pingback”
• enables reverse linking
• automatically notify original blog when sites link to it
<a rel="pingback" href="http://blog.blogspot.com">A Blog</a>
rel=”prefetch”
• hint for the browser that the resource is likely to be
used
11
@googledevlatam #devfest10
Tuesday, November 2, 2010 11
13. REL Attributes
rel=”pingback”
• enables reverse linking
• automatically notify original blog when sites link to it
<a rel="pingback" href="http://blog.blogspot.com">A Blog</a>
rel=”prefetch”
• hint for the browser that the resource is likely to be
used
<a rel=”prefetch” href=”nextPage.html”>Next page ></a>
11
@googledevlatam #devfest10
Tuesday, November 2, 2010 11
14. Data Attributes
<output id="out" data-id="good" data-name="joe"
data-screen-name="user1"></output>
var a = [], el = document.querySelector('#out');
el.setAttribute('data-foo', 'bar');
for (var key in el.dataset) {
a.push('<b>', key, '</b>: ',
el.dataset[key], '<br/>');
}
el.innerHTML += a.join('');
id: good
name: joe
screenName: user1
foo: bar
12
@googledevlatam #devfest10
Tuesday, November 2, 2010 12
15. HTML5 Forms
• New <input> types: tel,
email, url, datetime, date,
month, week, time,
datetime-local, number,
range, color
• New attributes: placeholder,
required, autofocus,
pattern, min, max, step,
speech, multiple, directory
• ....you don’t need JS libraries!
13
@googledevlatam #devfest10
Tuesday, November 2, 2010 13
16. Demos
open
14
@googledevlatam #devfest10
Tuesday, November 2, 2010 14
17. Web Storage
not just for offline
15
@googledevlatam #devfest10
Tuesday, November 2, 2010 15
18. Web Storage APIs
localStorage
• key/value pairs
• great for storing user preferences
localStorage.dateOfBirth = ‘1984-07-22’;
delete localStorage.dateOfBirth;
localStorage[‘user’] = JSON.stringify({username: john, id: 100});
var retrieved = JSON.parse(localStorage[‘user’]);
sessionStorage
• non-persistent key/value pairs (e.g. sensitive data)
Web SQL DB
• 5MB of persistent storage
• reduces round trips to the server
16
@googledevlatam #devfest10
Tuesday, November 2, 2010 16
19. var webdb = {};
webdb.open = function() {
webdb.db = openDatabase('Todo', '1.0', 'todo-manager', 5*1024*1024); //5MB
};
webdb.onError = function(tx, e) { alert('Error ' + e.message); };
webdb.onSuccess = function(tx, r) {
// re-render all the data in the DOM.
};
webdb.createTable = function() {
webdb.db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS ' +
'todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)', []);
});
};
webdb.addTodo = function(todoText) {
webdb.db.transaction(function(tx){
var addedOn = new Date();
tx.executeSql('INSERT INTO todo(todo, added_on) VALUES (?,?)',
[todoText, addedOn], webdb.onSuccess, webdb.onError);
});
};
17
@googledevlatam #devfest10
Tuesday, November 2, 2010 17
20. 4th Storage Option...
Indexed DB
• Hybrid of localStorage/sessionStorage APIs
and Web SQL DB.
• In-order retrieval
• Faster search - Index on any keys
• Browser support is still sparse
• Implemented in FF4
• Recently landed in Chromium: webkitIndexedDB
18
@googledevlatam #devfest10
Tuesday, November 2, 2010 18
21. Application Cache
• Caches entire web app locally
• Server with mime-type: text/cache-manifest
• Why?
1.HTML, CSS, and JS stay fairly consistent
2.Native browser caching is unreliable
3.Caching resources creates speedier apps
• Native iPhone & Android Gmail app uses
AppCache
19
@googledevlatam #devfest10
Tuesday, November 2, 2010 19
22. Cache Manifest File
<html manifest="example.manifest">... </html>
CACHE MANIFEST
# 2010-08-10-v0.0.1
# Explicitly cached entries
CACHE:
index.html
stylesheet.css
images/logo.png
scripts/main.js
# static.html will be served if the user is offline
FALLBACK:
/ /static.html
# Resources that require the user to be online.
NETWORK:
*
# login.php
# http://api.twitter.com
20
@googledevlatam #devfest10
Tuesday, November 2, 2010 20
23. JavaScript API
var appCache = window.applicationCache;
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); // Fetch was successful, swap the new cache.
}
appCache.addEventListener('cached', handleCacheEvent, false);
appCache.addEventListener('checking', handleCacheEvent, false);
appCache.addEventListener('downloading', handleCacheEvent, false);
appCache.addEventListener('error', handleCacheError, false);
appCache.addEventListener('noupdate', handleCacheEvent, false);
appCache.addEventListener('obsolete', handleCacheEvent, false);
appCache.addEventListener('progress', handleCacheEvent, false);
appCache.addEventListener('updateready', handleCacheEvent, false);
21
@googledevlatam #devfest10
Tuesday, November 2, 2010 21
26. Dedicated Workers: Getting Stuff Done
• Take advantage of multi-core CPUs
• Use cases:
• Text formatting of a long document
• Syntax highlighting
• Audio synthesis
• Image processing
• Processing large arrays or other
computational tasks
24
@googledevlatam #devfest10
Tuesday, November 2, 2010 24
27. JavaScript API
<output id="result"></output>
<script>
var worker = new Worker('task.js');
worker.onmessage = function(e) {
document.querySelector('result').textContent = JSON.stringify(e.data);
};
worker.postMessage(’start’);
</script>
importScripts('script1.js', ‘script2.js’);
self.addEventListener('message', function(e) {
switch (e.data) {
case 'start':
self.postMessage({'id': '12345', 'txt': 'Hi'});
break;
case 'stop':
self.close(); // Terminates the worker.
};
}, false);
25
@googledevlatam #devfest10
Tuesday, November 2, 2010 25
28. Inline Workers
<!DOCTYPE html>
<html>
<body>
<script id="worker1" type="text/html">
onmessage = function(e) {
...
};
</script>
<script>
var bb = new BlobBuilder();
bb.append(document.querySelector('#worker1').textContent);
var worker = new Worker(window.createObjectURL(bb.getBlob()));
worker.onmessage = function(e) {
...
};
worker.postMessage(); // Start the worker.
</script>
</body>
</html>
26
@googledevlatam #devfest10
Tuesday, November 2, 2010 26
29. WebSockets: Realtime
• Bi-directional communication
• Eliminates need for XHR polling!
• Close as we can get to TCP/IP socket connections in JS
• Port 80 - ws://
Port 443 - wss://
• Use cases:
• chat rooms
• white boarding
• games
27
@googledevlatam #devfest10
Tuesday, November 2, 2010 27
30. Javascript API
var ws = new WebSocket("ws://www.example.com/path");
ws.onopen = function () { // connection established
ws.send("Hello, WebSocket");
};
ws.onmessage = function(evt) {
alert(evt.data);
ws.close();
};
ws.onclose = function () {
// connection closed
};
28
@googledevlatam #devfest10
Tuesday, November 2, 2010 28
45. Is HTML5 Ready?
41
@googledevlatam #devfest10
Tuesday, November 2, 2010 41
46. Text
caniuse.com
42 Google Developer Day 2010
Tuesday, November 2, 2010 42
47. Modernizr Library
• BAD: checking navigator.userAgent
• Unreliable - users change this!
• BETTER: Feature detection
• Tests 20+ HTML5/CSS3 features:
document.createElement(‘nav’)
• Global Modernizr object with boolean
property for each feature
• Adds classes to the <html> element
that explain precisely what features are
(and are not) natively supported
43
@googledevlatam #devfest10
Tuesday, November 2, 2010 43
48. Usage
<div id="audio">
<audio>
<source src="mySong.ogg" />
<source src="mySong.mp3" />
</audio>
<button id="play">Play</button>
<button id="pause">Pause</button>
</div>
/* In your CSS: */
.no-audio #audio {
display: none; /* Don't show Audio options */
}
.audio #audio button {
/* Style the Play and Pause buttons nicely */
}
// In your JavaScript:
if (Modernizr.audio) {
// Hook up functionality to Play and Pause buttons
}
44
@googledevlatam #devfest10
Tuesday, November 2, 2010 44
49. Google Chrome Frame
1.Add a single meta tag to your site
• if !installed: direct users to download
• else: your site ‘just works’
<meta http-equiv="X-UA-Compatible" content="chrome=1">
2.Add a response header
X-UA-Compatible: chrome=1
45
@googledevlatam #devfest10
Tuesday, November 2, 2010 45
50. Thanks!
• Tools
• Google Fonts API: code.google.com/apis/webfonts/
• html5rocks.com
• Compatibility:
• Google Chrome Frame: http://code.google.com/chrome/chromeframe/
• caniuse.com
• modernizr.com
• File bugs against Chrome: crbug.com
• Stay in Touch!
• Twitter: @ChromiumDev
• groups.google.com/a/chromium.org/group/chromium-html5/
46
@googledevlatam #devfest10
Tuesday, November 2, 2010 46
51. Questions?
Stay up to date: @googledevbr
47
@googledevlatam #devfest10
Tuesday, November 2, 2010 47