ALL YOU NEED
TO KNOW ABOUT
JAVASCRIPTLOADING AND EXECUTION
IN THE BROWSER
<SCRIPT language="JavaScript">
//<![CDATA[
alert('
');
//]]>
</SCRIPT>
@sergio_caelum
sergiolopes.org
<script src="/js/main.js"></script>
THE END
THE END?
HOW BROWSERS
LOAD AND EXECUTE JS
disclaimer
HOW BROWSERS
LOAD AND EXECUTE JS
<html>
<head>
<script src="main.js"></script>
</head>
<body>
...
</body>
</html>
JS BLOCKS RENDERING
JS BLOCKS RENDERING
JS BLOCKS RENDERING
NETWORK LATENCY
PARSING TIME
EXECUTION TIME
AVAILABILITY (SPOF)
PUT JS AT BOTTOM
<html>
<head>
<script src="main.js"></script>
</head>
<body>
...
</body>
</html>
<html>
<head>
</head>
<body>
...
<script src="main.js"></script>
</body>
</html>
DEFER
<html>
<head>
<script src="main.js" defer></script>
</head>
<body>
...
</body>
</html>
<html>
<head>
<script src="main.js" defer></script>
<script src="other.js" defer></script>
</head>
<body>
...
</body>
</html>
PUT JS AT BOTTOM
PLUS: NO NEED FOR $(document).ready(..) ANYMORE
MULTIPLE SCRIPTS
<script src="jquery.js"></script>
<script src="jquery.plugin.js"></script>
<script src="application.js"></script>
...
LATENCY
SCRIPT CONCATENATION
SCRIPT CONCATENATION
1 SCRIPT? 2 SCRIPTs?
SEQUENTIAL EXECUTION
ASYNC LOADING
var js = document.createElement('script');
js.src = 'script.js';
document.head.appendChild(js);
<script src="main.js" async></script>
<script src="other.js" async></script>
<html>
<head>
<script src="main.js" async></script>
<script src="other.js" async></script>
</head>
<body>
</body>
</html>
EXECUTION ORDER?
SEPARATE DOWNLOAD
FROM EXECUTION
<script src="main.js" type="bla"></script>
<script src="main.js"></script>
<script src="main.js"></script>
/*
alert('Everything commented out');
...
*/
<script src="main.js"></script>
/*
alert('Everything commented out');
...
*/
eval(js_code_inside_comments);
new Image().src = 'script.js';
new Image().src = 'script.js';
<script src="script.js"></script>
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function(js){
if (ajax.readyState == 4)
// execute js in order
};
ajax.open('script.js');
ajax.send();
Ajax
var js = document.createElement('script');
js.src = 'script.js';
IE
var js = document.createElement('script');
js.src = 'script.js';
IE
js.onreadystatechange = function(){
if (js.readyState == 'loaded')
document.head.appendChild(js);
};
var js = document.createElement('script');
js.preload = true;
js.onpreload = function(){
// ...
};
js.src = 'script.js';
preload=true
var js = document.createElement('script');
js.async = false;
js.src = 'script.js';
document.head.appendChild(js);
async=false
SCRIPT LOADERS
$LAB.script('jquery.js').wait()
.script('plugin1.js')
.script('plugin2.js')
.script('plugin3.js').wait()
.script('application.js');
LABjs
DISCOVERABILITY
<script src="labjs.js"></script>
<script>
$LAB.script('jquery.js').wait()
.script('plugin1.js')
.script('plugin2.js')
.script('plugin3.js').wait()
.script('application.js');
</script>
<script>
/* inline ~2KB do LABjs */
</script>
<script>
$LAB.script('jquery.js').wait()
.script('plugin1.js')
.script('plugin2.js')
.script('plugin3.js').wait()
.script('application.js');
</script>
LOOK AHEAD PRE-PARSER
<link rel="prefetch" href="script.js">
<link rel="subresource" href="script.js">
<link rel="subresource prefetch" href="scri
ASYNC EXECUTION
<script src="script1.js" async></script>
<script src="script2.js" async></script>
<script src="script3.js" async></script>
DEPENDENCIES?
order != dependency
<script src="script1.js"></script>
<script src="script2.js"></script>
<script src="script3.js"></script>
<script src="script4.js"></script>
<script src="script5.js"></script>
AMD
ASYNCHRONOUS MODULE DEFINITION
* OR SOMETHING SIMILAR
$('#panel').fadein();
define('app', ['jquery'], function($) {
});
$('#panel').fadein();
var jQuery = // ...
var jQuery = // ...
function() {
return jQuery;
}
define('jquery',[],
);
var jQuery = // ...
function() {
return jQuery;
}
BETTER CODE
ASYNC DEPENDENCY
EXECUTION
Require.js
<script src="require.js"
data-main= "myapp"></script>
<script src="require.js"
data-main= "myapp"></script>
myapp.js
<script src="require.js"
data-main= "myapp"></script>
myapp.js
mymodel.js mycontroller.js
<script src="require.js"
data-main= "myapp"></script>
myapp.js
mymodel.js mycontroller.js
util.js plugin1.js plugin2.js
<script src="require.js"
data-main= "myapp"></script>
myapp.js
mymodel.js mycontroller.js
jquery.js
util.js plugin1.js plugin2.js
BUILD
r.js + almond
r.js + almond
r.js -o baseUrl=. name=almond include=main out=all.js wrap=true
<script src="all.js"></script>
myapp.js
mymodel.js mycontroller.js
jquery.js
util.js plugin1.js plugin2.js
all.js
almond.js
myapp.js
mymodel.js mycontroller.js
jquery.js
util.js plugin1.js plugin2.js
almond.js
base.js
mypage.js
<script src="base.js"></script>
<script src="mypage.js"></script>
<script>/* 250b AMD define */</script>
<script src="base.js" async></script>
<script src="modules.js" async></script>
<script src="more.js" async></script>
FUTURE
TEST: 200 JS modules,~13KB each
#1
200 .js files + 1 HTML file
<script async>
HTTP
TEST: 200 JS modules,~13KB each
#2
1 .js file + 1 HTML file
<script async>
HTTP
TEST: 200 JS modules,~13KB each
#3
200 .js files + 1 HTML file
<script async>
SPDY
200 files
1 file
0 12500 25000 37500 50000
HTTP:
200 files
1 file
200 files
1 file
0 12500 25000 37500 50000
HTTP:
SPDY:
SPDY & HTTP 2.0
FUTURE #2
module utils {
var local = 0;
export var exposed = "Public API";
}
Modules
Modules
module main {
import exposed from utils;
console.log(exposed);
}
ES-HARMONY
<script>
defer
async
SCRIPT LOADERS
prefetch / subresource
AMD
require.js / r.js / almond
SPDY & HTTP 2
ES-HARMONY MODULES *
ALL YOU NEED
TO KNOW ABOUT
JAVASCRIPTLOADING AND EXECUTION
IN THE BROWSER
<SCRIPT language="JavaScript">
//<![CDATA[
alert('
');
//]]>
</SCRIPT>
THANK YOU
sergiolopes.org
@sergio_caelum
<SCRIPT language="JavaScript">
//<![CDATA[
alert('
');
//]]>
</SCRIPT>

All you need to know about JavaScript loading and execution in the browser - JSConf BR 2013