@dbjdbj:
I wouldn't be as clear cut as you are, but it's true Zoho's post editor is a pain.
@james:
Nice reply with lots of sensible arguments :)
I would have answered earlier, but my isp failed me this week-end... :(
In particular, I'd like to answer regarding this, though:
I believe a runtime rules approach as used in Dominoes optimizes for something that normally does not need optimization. During development, a developer just wants to worry about a file/module's direct dependencies, then get to coding. Then, when considering deployment, a wider dependency analysis needs to be done. However, for deployment there are normally other packaging tasks that are done, so it seems reasonable to specify the rules for module optimizations during a build process that can be done during that packaging step.
The dependency analysis you refer to is limited to a single domain. I think we have a misunderstanding regarding what I call "same-domain orientation" for current loaders in use. And the developper you refer to is a website developper not a plugin developper.
Let's take the following () situation:
- Julian writes a nice twitter plugin that will reside into a div. All you have to do is remote linking to the script at google-code and then call $("#aDiv").juliansNiceTwitterApp( options );
- James writes an awesome feed syndicator plugin using yql. All you have to do is remote linking to the script at google-code and then call $("#anotherDiv").jamesAwesomeFeedSyndicator( options );
- and John made a cool templating engine plugin back in the days. You can get it by remote linking to the script on john's site then call $("#target").applyJohnsNeatTemplateEngine( templateCode, jsonData);
Both Julian's & James' plugins make use of John's templating plugin but, rather than integrating the source of John's plugin into their own, they decided to remote link to the script using a javascript loader. They also make use of the latest jQuery 1.5 modularized system hosted by google to have good performances even on mobile phones.
Now, that's dynamic loading, but since the twitter status app and the feed syndication are not essential to the site, it's a good demonstration of lazy loading, right?
But here is the deal. There are 3 jQuery 1.5 hosted on google (1.5.1, 1.5.2 and 1.5.3 -- John Resig being on a release frenzy). Julian's plugin was written when 1.5.1 was out and hasn't been updated since, James' just got released (and uses 1.5.3 specific features) and John's code is not maintained anymore and happens to be be a good old plugin with a ( function($) { ... } )( jQuery ); type of closure (and is actually compatible with jQuery 1.3 though it only needs jQuery:core and jQuery:manipulation when looking at it from a modularized perspective).
To add to the difficulty, the site owner is already using a nightly build of jQuery (1.5.4pre) because it fixes a nasty issue he had with 1.5.3 and would much prefer that all three plugins use this version of the lib (actually "remote linking" to his site) while waiting for 1.5.4 to be released and hosted on google.
The solution with current loaders are as follows:
- make a local copy of each plugin and edit their code appropriately, eventually using a preprocess server-side to concatenate files, completely derailing the very notion of remote-linking,
- Use iframes to separate everyone having jQuery 1.5.1, 1.5.3 and 1.5.4pre modules + *twice* John's templating plugin loaded for the very same page. I won't even comment here, but let's observe this is what most pluggable sites do nowadays.
Here is how I'd solve the problem with "unnecessary" runtime rules... :P :
First, let's make Julian's and James' plugins jQuery and John's templating engine version (and even location for jQuery) agnostic:
- ( function( dominoes ) {
- // Define a default URL if no jQuery rule already exists
-
- dominoes.rule.ifNot( "jQuery" ,
- "http://ajax.googleapis.com/ajax/libs/jquery/1.5.X/jquery.core.min.js" );
-
- // Then load & execute stuff
-
- dominoes( {
-
- chain: "jQuery > ( jQuery:manipulation > templateLib ) jQuery:json
-
- templateLib:
-
- jQuery.fn.applyJohnsNeatTemplateEngine
-
- ? dominoes.noo
-
- : "http://ejohn.org/template-1.X.min.js",
-
- createPlugin: function() {
- // Plugin code
-
- }
-
- } );
- } )( dominoes );
Then, here is how the page would actually declare stuff:
- // ON TOP: Declare jQuery rule
- dominoes.property( "jQuery:DIR" , "js/1.5.4pre" )
- .rule( "jQuery" , "$(jQuery:DIR)/jQuery.core.min.js" );
- // Do some stuff using jQuery on the page
- dominoes( "jQuery >|" , function() {
- // Some DOM manipulation
- } );
- // Load James' plugin
- dominoes( "http://jamesFeed.googlecode.com/files/jamesFeed-0.9.js >|" , function() {
- $("#divFeed").jamesAwesomeFeedSyndicator( options );
- } );
- // Load Julian's plugin
- dominoes( "http://julianTweeter.googlecode.com/files/julianTweeter-1.1.3.js >|" , function() {
- $("#divTweeter").juliansNiceTwitterApp( options );
- } );
The code above will only load *1* version of jQuery (the one on the dev's site), *1* version of each jQuery module (again from the website of the dev), John's, James' and Julian's plugin once each and remotely.
Plugin code takes some plumbery but it should since it has some controlling to do before feeding Dominoes a default URL. Please note there are a lot of ways to do what the plugin code does and the one here is just an example.
Site code is VERY straight-forward (the developper only has to think of which files he needs and code right away). Also all it takes the maintainer when 1.5.4 is out and hosted on google is to replace "js/1.5.4pre" with "http://ajax.googleapis.com/ajax/libs/jquery/1.5.4". I don't see that as something cryptic or difficult.
If the jQuery module rules are implemented using a Cumulator, the code above will result in 5 requests to 3 different domains:
1) jQuery.core.js, James' and Julian's plugins in parallel,
2) then manipulation + ajax + jsonp from the dev's site for the modules ( provided the rule jQuery:jsonp establishes the dependency to jQuery:ajax which makes sense and I'd recommend it ) in parallel with John's templating plugin (as defined by the first of James' or Julian's plugin to be loaded)
If the website dev wants to ensure a specific version of John's templating engine to be used, he can simply add a dependency to the two last statements: jQuery.fn.applyJohnsNeatTemplateEngine will be defined when the two other plugins are loaded so this specific version would be used.
What I'm talking about here is cross-domain dependency, complete control over what is loaded and when and that without sacrificing js file concatenation if a provider supports it. You can use the code above even on a website with no server control where you can only edit HTML if you keep it to remote linking (think blogger.com).
Of course, if you are AOL, you don't need this since you have the bandwidth and frequentation to handle js file delivery yourself and go the server-side building way.
Anyway, that's what I meant by "cross-domain": true cross-site dependency handling. Sorry for the lengthy post, just wanted to make that clear.
And again, thanks for the very argumented answer, these are always a pleasure to read :)