Supporting AMD

From: AMD wiki

I think Yii2 could ship an AMD-loader like RequireJS or curl. This loader could be used internally by the ClientScript class or maybe also by the asset manager (didn’t elaborate on this, but at least RequireJS supports optimization of scripts, so maybe this could be done when publishing assets in production mode).

jQuery can be loaded as AMD module since v1.7. jQuery UI doesn’t support it yet, but it seems like it is not too difficult to turn the widgets into AMD modules (see here).

I stumbled over this when I was playing with backbone to implement a facebook app. Very soon, I encountered some problems like backbone depending on jQuery and underscore (both need to be loaded before backbone), race conditions between jQuery’s ready event and facebook sdk’s asyncInit, …

Finally I decided to give curl a try, and it seems to do a good job. I still miss lazy-loading dependencies, but I’m not sure if this is covered by AMD. Also, loading non-AMD scripts like underscore and backbone was no problem, so it seems like using the loader does not mean you limit yourself to AMD modules only.

What do you think about it?

// EDIT: add link to AMD wiki

At a first glance: Looks cool :)

Many scripts like Backbone JS refuse to work with AMD, I don’t think it’s the way to go…

True, backbone and underscore both decided not to go this way. If you’re interested in their reasons, you can read about them here:

Pull request to add AMD support (rejected)

Kind of an answer to this decision

Or to follow the whole story:

Backbone Issue #684

Backbone Pull Request #688

Backbone Pull Request #710

Underscore Pull Request #431

I don’t have much experience with using AMD modules, so I can’t tell if their approach is the way to go. It’s only that it seems like a good concept to me.

And to come back to backbone: I had no trouble using it together with curl. It was something like:




// app.js

// defines the application

define(


  // dependencies

  [

    'jquery',

    'js!underscore/underscore.js!order',  // js plugin loads plain javaScript files, order ensures that backbone

    'js!backbone/backbone.js!order'       // is loaded after underscore

  ],


  function( $ ) {

    Backbone.setDomLibrary( $ );


    // use Backbone to create app views, models, ...

 

    return app;

  }


);






// app.php

// yii layout that renders a very tiny html document containing a <div id="app" /> to host the app

<html>

<head>...</head>

<body>


<div id="app" />


<script>

curl(


  // dependencies

  [

    'jquery',

    'app/app'

  ],

  

  function( $, app ) {

    app.run( $('#app') );

  }

  

);

</script>

</body>

</html>



So in this case, although using non-AMD scripts, the script loader still helped me:

  • In the layout, I don’t have to care about the dependencies of the application I load (it defines its dependencies on its own)

  • The correct order of dependencies is only important when loading non-AMD modules (hopefully fewer as time goes by)

  • The script loader cares for asynchronous script loading (as far as it can - we forced underscore and backbone to load in order). No more blocking of web page rendering.