2. Loading Javascript
These slides are
not about:
detailing defer/FIF js
embedding on site
or putting the js after the
body or in the head
These slides are
supposed to be
about:
detailing why static js
loading, packaging and
building leads to nowhere
on the long run
and a possible solution
6. Code compilation / build
Much less http requests
Tools:
● concatenation
● uglify / yuicompressor
http://www.flickr.com/photos/halfbisqued/2353845688/
7. Code compilation / build
Compile all the js that the
current page might need:
Several smaller files
Compile all js that we need:
One huge file
Create js groups according to
page needs
http://www.flickr.com/photos/halfbisqued/2353845688/
8. Code compilation / build
Compile all the js that the
current page might need:
Several smaller files
Compile all js that we need:
One huge file
Create js groups according to
page needs
What is the problem with that?
http://www.flickr.com/photos/halfbisqued/2353845688/
11. The new killer feature, that saves us!
Click here to
close
12. Code compilation / build
The given feature is used on the page,
or
The visitor might use it on the page
"the current page might need"
One page gets n+1 new feature:
The js compiled group for that page grows even more
heavy
Do we really need it onLoad?
Lots of unused code, that waits for the user:
overhead, slows load time.
http://www.flickr.com/photos/halfbisqued/2353845688/
13. Async loading!
Load only the most necessary js onLoad!
Then, for every feature the user wants,
load the js runtime.
http://www.flickr.com/photos/thenationalguard/8029811025/
● Feature based code, not page based
code
● Small lag in UX, but faster page start
● Loose module coupling, better code
14. Code compilation / build
Compile all the js that the
current page might need:
Several smaller files
Compile all js that we need:
One huge file
Create js groups according to
page needs
And what is the problem with that?
http://www.flickr.com/photos/halfbisqued/2353845688/
15. Dependency handling
The problem with predefined js
groups:
http://www.flickr.com/photos/wongjunhao/2761709029/
● add js by planned use
(add a feature, that can be used)
● add js by failsafe use
("this might come handy" or "make sure to have
this")
● group is built at deploy
16. Dependency handling
The group is created for a
planned usage
The group contents has nothing
to do with the real functioning
site or app
http://www.flickr.com/photos/wongjunhao/2761709029/
17. Dependency handling
Let the js codebase define it's own
dependency
Here come the modules!
AMD
(Asynchronous Module Definition)
Designed for the
web
CommonJS
Designed for the
server (nodejs)
http://www.flickr.com/photos/wongjunhao/2761709029/
18. Dependency handling
AMD structure
define (
// optional, used in build code
'moduleName',
// dependencies
['modules/Module1', 'modules/Module2'],
// module definition
function (module1, module2) {
});
http://www.flickr.com/photos/wongjunhao/2761709029/
19. Async loading + Modules
Module loader
a javascript utility, that:
● handles module definitions and
requirements
● loads modules from a remote
server
require.js, curl.js, etc
http://www.flickr.com/photos/redux/4298421692/
20. Async loading + Modules
Require.js example
http://www.flickr.com/photos/redux/4298421692/
Every dependency starts a new request
Lots of requests - not very good
21. Async loading + Modules
Need fewer requests?
Introduce async packaging!
http://www.flickr.com/photos/redux/4298421692/
Request and load packaged javascripts
async, instead of each file.
But how will the client know of the
available package list?
22. Async loading + Modules
Possible solution:
expose the built package list, and contents
to the client
http://www.flickr.com/photos/redux/4298421692/
Why not?
In case of a large codebase, this can be an
uncomfortably large amount of data. Also,
exposes the whole codebase to the client.
23. Async loading + Modules
Another problem with pre-built packages,
prepared for async load:
Overlapping dependencies are inevitable
http://www.flickr.com/photos/redux/4298421692/
Pack_1 Pack_2 Pack_3
Foo.js Foo.js
Bar.js Bar.js
Either package every common
dependency, every time it's needed...
24. Async loading + Modules
Overlapping dependencies...
Or put those commons to the page
onLoad
http://www.flickr.com/photos/redux/4298421692/
Pack_1 Pack_2 Pack_3
Pack_onLoad Foo.js Bar.js
Codebase at onLoad starts grow fast,
getting slower pageload :(
25. Async loading + Modules
So...
http://www.flickr.com/photos/redux/4298421692/
Either we have lots of
requests
Or big files, with massive
redundancy and
duplicated code.
Pack_1
Pack_2
Pack_3
Foo.js
Foo.js
Bar.js
Bar.js
26. Async loading + Modules
Are we keep circling around the
same issue?
http://www.flickr.com/photos/redux/4298421692/
27. JS Module Server
Time to rethink the way of
serving javascript instead of
loading it as a fully static asset.
Put the dependency handling to
the server side.
http://www.flickr.com/photos/alca_impenne/4295937972/
28. JS Module Server
Credit where it's due!
Malte Ubl & John Hjelmstad
http://www.youtube.com/watch?v=mGENRKrdoGY
Two guys at Google/Gmail
http://www.flickr.com/photos/alca_impenne/4295937972/
29. JS Module Server
Request just one module, the
server finds it's dependencies,
packs and serves.
/js/+app/Foo.js
On the client side, we keep track
of what modules have been
requested already.
http://www.flickr.com/photos/alca_impenne/4295937972/
30. JS Module Server
At the next requested module, we
tell the server which modules
were requested already
(note: not all the received, just the requested)
These are "subtracted" from the
request
/js/+app/Bar-app/Foo.js
http://www.flickr.com/photos/alca_impenne/4295937972/
31. JS Module Server
/js/+app/Bar-app/Foo.js
The server takes the requested module
dependencies, and subtracts all those, that
have been served for the client already.
The new package only contains code
that haven't been loaded by the client.
http://www.flickr.com/photos/alca_impenne/4295937972/
33. JS Module Server
Providing solution for:
" lots of requests "
Thinking in feature-oriented code, instead of the page-
oriented code, these async loads can refer to only the
requested feature. One request per feature.
" big files, with massive redundancy and duplicated code "
Only that code is packaged, that haven't been served
already.
http://www.flickr.com/photos/alca_impenne/4295937972/
34. JS Module Server
Additional gains
● full i18n support (can require groups by locale)
● cacheable urls
● sourcemap support (via uglify2)
● the full codebase is loaded by the
server, it can run tasks on it, debug
output, etc. (strip all console.* for example)
● could handle CSS later (with supporting
preprocessors like SASS/LESS)
http://www.flickr.com/photos/alca_impenne/4295937972/
35. JS Module Server
● Parallel requests
(add a counter-callback parameter,
which determines the right parse order
for the module loader, like JSONP)
● Handle browser cache properly
(this one is a tricky one, but we're on
the way. Changing the url is 100% sure,
but If-Modified-Since would be nicer)
Things to be done
http://www.flickr.com/photos/alca_impenne/4295937972/
36. JS Module Server
Things to be done
● Put it to production
(soon on Ustream)
● Open source it
(soon on GitHub)
http://www.flickr.com/photos/alca_impenne/4295937972/