This document discusses strategies for improving JavaScript performance on web pages. It begins by noting that JavaScript is often the number one cause of slow page loads. It then reviews the history of script loading approaches, from loading scripts in the page head in 1995 to more modern async and deferred loading. Key recommendations include using async and deferred loading, prefetching scripts that may not be needed, leveraging localStorage as an application cache, and optimizing the Google Analytics async snippet. The document emphasizes strategies from stevesouders.com like ControlJS and leveraging tools from sites like WebPagetest.org and Cuzillion.com to test performance.
10. 1995: scripts in HEAD
<head>
<script src=‘a.js’></script>
</head>
blocks other downloads (IE 6-7, images
in IE, iframes)
downloaded sequentially (IE 6-7)
blocks rendering during download &
parse-execute
11. 2007: move scripts to bottom
...
<script src=‘a.js’></script>
</body>
doesn’t block other downloads
downloaded sequentially in IE 6-7
blocks rendering during download &
parse-execute
12. 2009: load scripts async
var se =
document.createElement(‘script’)
;
se.src = ‘a.js’;
document.getElementsByTagName(‘he
ad’)[0].appendChild(se);
doesn’t block other downloads
downloaded in parallel (all browsers)
blocks rendering during parse-execute
13. 2010: async + on-demand exec
var se = new Image(); // Object
se.onload = registerScript;
se.src = ‘a.js’;
separate download from parse-execute
doesn’t block other downloads
downloaded in parallel (all browsers)
doesn’t block rendering until demanded
15. script async & defer
parsing doesn’t wait for script:
• async – executed when available
• defer – executed when parsing finished
when is it downloaded?
missing:
• defer download AND execution
• async/defer download, execute on demand
16. 20??: markup
<script src=‘a.js’
[async|defer|noexecute]
[deferdownload]>
doesn’t block downloads
downloaded in parallel
doesn’t block rendering until demanded
doesn’t contend for a connection
easier
17. ControlJS
a JavaScript module for making scripts load faster
just change HTML
inline & external scripts
<script type=‘text/cjs’
data-cjssrc=‘main.js’>
</script>
<script type=‘text/cjs’>
var name = getName();
</script>
http://controljs.org/
18. ControlJS
a JavaScript module for making scripts load faster
download without executing
<script type=‘text/cjs’
data-cjssrc=‘main.js’
data-cjsexec=false>
<script>
Later if/when needed:
CJS.execScript(src);
19. GMail Mobile
<script type=‘text/javascript’>
/*
var ...
*/
</script>
get script DOM element's text
remove comments
eval() when invoked
awesome for prefetching JS that might
(not) be needed
http://goo.gl/l5ZLQ
23. Home screen apps on iPhone are slower
because resources are re-requested
even though they should be read from
cache.
24. localStorage
window.localStorage:
setItem()
getItem()
removeItem()
clear()
also sessionStorage
all popular browsers, 5MB max
http://dev.w3.org/html5/webstorage/
http://diveintohtml5.org/storage.html
25. localStorage as cache
1st doc: write JS & CSS blocks to localStorage
mres.-0yDUQJ03U8Hjija: <script>(function(){...
set cookie with entries & version
MRES=-0yDUQJ03U8Hjija:-4EaJoFuDoX0iloI:...
later docs: read JS & CSS from localStorage
document.write( localStorage.getItem(mres.-
0yDUQJ03U8Hjija) );
http://stevesouders.com/blog/2011/03/28/storager-case-
study-bing-google/
26. Google Analytics Async Snippet
var ga = document.createElement(‘script’);
ga.type = ‘text/javascript’;
ga.async = true;
ga.src = (‘https:’ ==
document.location.protocol ? ‘https://ssl’ :
‘http://www’)+‘.google-analytics.com/ga.js’;
var s =
document.getElementsByTagName(‘script’)[
0];
s.parentNode.insertBefore(ga, s);
code.google.com/apis/analytics/docs/tracking/asyncTracking.html
27. var ga = document.createElement(‘script’);
ga.type = ‘text/javascript’;
ga.async = true;
ga.src = (‘https:’ ==
document.location.protocol ? ‘https://ssl’ :
‘http://www’)+‘.google-analytics.com/ga.js’;
var s =
document.getElementsByTagName(‘script’)[
0];
s.parentNode.insertBefore(ga, s);
avoid mixed content warning
protocol relative URLs have problems
set src last
stevesouders.com/blog/2010/02/10/5a-missing-schema-double-download/
28. var ga = document.createElement(‘script’);
ga.type = ‘text/javascript’;
ga.async = true;
ga.src = (‘https:’ ==
document.location.protocol ? ‘https://ssl’ :
‘http://www’)+‘.google-analytics.com/ga.js’;
var s =
document.getElementsByTagName(‘script’)[
0];
s.parentNode.insertBefore(ga, s);
previously:
getElementsByTagName(‘head’)[0].
appendChild(ga)
HEAD might not exist
stevesouders.com/blog/2010/05/11/appendchild-vs-insertbefore/
Android 1.5, iPhone 3.0, Opera 8.50, Safari 3.2
stevesouders.com/blog/2010/05/12/autohead-my-first-browserscope-user-test/
29. var ga = document.createElement(‘script’);
ga.type = ‘text/javascript’;
ga.async = true;
ga.src = (‘https:’ ==
document.location.protocol ? ‘https://ssl’ :
‘http://www’)+‘.google-analytics.com/ga.js’;
var s =
document.getElementsByTagName(‘script’)[
0];
s.parentNode.insertBefore(ga, s);
some browsers preserve execution order
Firefox 3.6, Opera, OmniWeb
stevesouders.com/tests/jsorder.php
3.777 seconds - http://www.webpagetest.org/result/120111_0P_2TW4Q/ - block “.js” (it’s not downloaded)5.471 seconds - http://www.webpagetest.org/result/120111_GR_2TW90/Alexa top 100wwide
median: 3.650vs 2.4873.777 seconds - http://www.webpagetest.org/result/120111_0P_2TW4Q/ - block “.js” (it’s not downloaded)5.471 seconds - http://www.webpagetest.org/result/120111_GR_2TW90/Alexa top 100wwide
flickr.com/photos/gevertulley/4771808965/Generallyasync & defer scripts start downloading immediately. I wish they’d wait, esp. defer scripts, so they don’t hog connections from the limited pool.subatomic particle traces