Feature Proposal: Lazy Load Javascript and Css
Motivation
As I use javascript popup dialogs more, I find myself needing to get javascript loaded dynamically - some dialogs need charting that isn't present in the loaded topic, or (the currently obvious one -
strikeone.js for popup task creation)
it would give us a more dynamic js REQUIRE implementation than we currently have - where the js knows its loaded, so doesn't need to re-load, can load implied dependencies, obey ordering, and generally walk and chew gum at the same time.
additionally, there seems to be a meme about the speed / non-blocking download aspects of doing things this way (the html5 async attr may address this, but not the other possible advantages)
I wold also like to have the ability to trigger an even when the async things are ready
Description and Documentation
there are a few blogs about the development of solutions:
implementations :
Examples
I really would like to just add
REQUIRE{strikeone} to something and know that it'll happen irrespective of normal topic view, or delayed load.
or if using a jqDialog css param - to not require anything at all - it'll just know... (yeah, that might be dreaming but meh.)
so presumably there will need to be a REQUIRE_MANIFEST that lists the js, html, css, dependencies, whatever that should be loaded - like JQREQUIRE, but generalised.
Impact
Implementation
--
Contributors: SvenDowideit - 18 Apr 2012
Discussion
Yes we need this for javascript. Not sure about css. At least optimizing css is easier.
Just for clarification: the main difference will be that instead crafting
script tags into the html header on the server side, we will add them on the client side after the DOM has been loaded. The browser will then have to decide which scripts to load and in which order.
Question: shall we
- (a) write our own lazy async loader or
- (b) use an existing one like RequireJS?
Things to watch out for:
FUBC (flash of unbehaviored content): there might be some js that manipulates the DOM massively as soon as it gets loaded. this might result in flickering or more rerendering than what we have now, or at least easier perceived by the user. Best examples are twisties and tinymce.
With regards to tinymce: there is a rather delicate javascript init process in the way tinymce is loaded into the page right now, i.e. it massively blocks page loading times by executing even
before the complete DOM is loaded. Not sure it is compatible with things like RequireJS.
We still generate inline scripts and styles per page. Makes things a bit tricky wrt execution order. From what I see now, only
LabJS can deal with this. Please prove me wrong studying the other loaders.
What about users adding javascript to the topic text? Which provisions will they have to follow to play nicely with the code loaded by Foswiki? It might need some macros to interact with the javascript loader.
RequireJS comes with a "module" concept of its own. This doesn't match well the way we plug things into foswiki atm.
HeadJS comes with lots of html5 "cruft" that is better done using
Modernizr, imho.
LabJS seems to be equivalent to HeadJS w/o the html5 stuff.
LabJS seems to demand the least overhead organizing javascript files on the backend. It just does what it should do: load the js files.
There's a clear migration path towards making use of LabJS.
Before:
<script src="framework.js"></script>
<script src="plugin.framework.js"></script>
<script src="myplugin.framework.js"></script>
<script>
myplugin.init();
</script>
<script>
framework.init();
framework.doSomething();
</script>
After:
<script>
$LAB
.script("framework.js").wait()
.script("plugin.framework.js")
.script("myplugin.framework.js")
.wait(function(){
myplugin.init();
framework.init();
framework.doSomething();
});
</script>
--
MichaelDaum - 18 Apr 2012
yeah - that was my impression about
LabJS and the others :/
--
SvenDowideit - 18 Apr 2012
Another twist to the problem is that content might be loaded async'ly, e.g. using
JQueryLoader or using
InfiniteScrollContrib. This markup then adds js and css requirements incrementally. For now the only way to deal with this is either to load all js and css before any async markup, or to inline css and js. The latter approach is not available when generating markup client side using
JQueryTmpl while reading json from the backend, as is the case in
SolrPlugin.
--
MichaelDaum - 15 Jan 2013
In the past I've just used
jQuery.getScript() - I realize this comment is perhaps unhelpful
--
PaulHarvey - 29 Jan 2013