This topic has been discussed in a couple other threads, but I don't feel like it's been resolved. So if I may, I'd like to initiate a more in-depth conversation about the pros/cons of one of Durandal's design decisions: using <script> tags to load 3rd-party libs (e.g., jQuery, Knockout, and Sammy) and only using AMD/require.js to load Durandal's modules.
[index.html]
...
<body>
<div id="applicationHost"></div>
<script type="text/javascript" src="Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="Scripts/knockout-2.2.1.js"></script>
<!--Durandal's core does not require SammyJS. The router plugin uses it.-->
<script type="text/javascript" src="Scripts/sammy-0.7.4.js"></script>
<script type="text/javascript" src="app/durandal/amd/require.js" data-main="app/main"></script>
</body>
</html>
Personally, I don't like this aspect of Durandal. I'd much rather use AMD/require.js to load everything (i.e., allow index.html to use a single <script> element). Unfortunately, Durandal is written in a way that assumes ko is globally defined. In other words, Knockout MUST be loaded via a <script> element in index.html, before main.js is loaded. Otherwise, Durandal's modules fail.
AFAIK, in order for Durandal to be completely executable through a single script element (and keep the global namespace clean), it would need to be modified such that all Durandal modules require jQuery and ko. In other words, changing this design aspect isn't exactly trivial--it would mean modifying several core Durandal files. Therefore, I think we should discuss the pros/cons of such a change and determine (once and for all) whether or not it would be appropriate.
I think Durandal should definitely change to a pure AMD architecture, so I'll begin the discussion by providing my own reasoning. Also, as a side note, I'll mention that I'm only using Durandal in the browser. Some of the benefits listed below might be attainable through a server build/optimization, but I'm assuming it's desirable for Durandal to accommodate high performance without requiring a server.
1. Keep the global namespace clean
Correct me if I'm wrong, but wasn't "global namespace pollution" one of the driving forces behind modular JS in the first place? It just seems really wrong to me that Durandal uses AMD/require.js and then forces developers to disregard the best practices AMD was designed to enforce. But more importantly, Durandal should change to a pure AMD architecture because it would allow for use cases where multiple versions/instances of jQuery and Knockout are present in the same document. Currently, Durandal assumes that $ and ko won't be used/modified by something else on the page; is that always a safe assumption? No.
2. Lazy-load the entire app
For the project I'm working on, index.html loads default content that doesn't have any JavaScript dependencies. Durandal kicks off after the page is done loading that default content (and optionally, after a User-initiated event, e.g., "Click here to load the application"). This allows for a very fast perceived load time, which is especially important for mobile devices. However, this is not possible with Durandal's current design (at least not without writing a significant amount of custom code).
3. Faster (perceived) page load
Even without lazy-loading, the perceived page load time can be significantly improved by using require.js to load 3rd-party scripts. By loading jQuery, Knockout, and Sammy with require.js (via a single script tag right before </body>), I was able to reduce the page load time (measured by the document's load event) from 4.2 seconds to 1.2 seconds.
4. CDN with local fallbacks
Using the require.config
paths configuration, let the app load 3rd-party scripts from a CDN; fallback to Durandal's copies. Example:
'text': 'durandal/amd/text',
'../Scripts/jquery-1.9.1.min'
'../Scripts/knockout-2.2.1'
Please...if anyone has anything to add here, feel free to chime in. I'm especially interested in hearing reasons for keeping Durandal the way it is (i.e., loading 3rd-party scripts via <script> tags and polluting the global namespace).