Elgg Blog: Elgg 1.9: AMD for JS Modules

As of Elgg 1.9, we are encouraging all developers to adopt the AMD (Asynchronous Module Definition) standard for writing Javascript code in Elgg.

For some time now, we have been working hard to make Elgg’s Javascript more maintainable and useful. We made some strides in 1.8 with the introduction of the “elgg” javascript object and library, but have quickly realized that based on the number of features we’d like to see added to the platform, the approach we were taking was not scalable. The size of JS on the web is growing quickly, and JS in Elgg is growing too. We want Elgg to be able to offer a solution that makes JS development as productive and maintainable as possible for everyone going forward.

What does this mean for me?

First thing’s first: Your current javascript modules will continue to work with Elgg. We do not anticipate any backwards compatibility issues with this new direction and will fix any issues that do come up. We think developing in the AMD format will be great, but we understand that you don’t always have the cycles to convert to The New Way immediately, so we want to give everyone flexibility to switch to the new standard when it’s most convenient for them. For developers ready to make the switch to AMD, read on.

Defining and loading a module in Elgg 1.9 currently takes three steps:

  1. Define your module in the appropriate view (js/my/module.js)*
  2. Register your view as cacheable (elgg_register_simplecache_view)**
  3. Use elgg_require_js to asynchronously execute your module in the current page.

Read on for details.

1. Define your module in the appropriate view (“js/my/module.js”)

Place the code for “my/module” at “views/default/js/my/module.js.php”. (Yes, “.js.php”)

A basic module will look like this:

define(function(require) {
var elgg = require("elgg");
var $ = require("jquery");

return function() { /** Some logic in here */ };
});

Now, someone can use require("my/module") in their code to get access to that function "exported" by your module.

Some things to note:

  1. elgg.provide and elgg.require are obsoleted, replaced by define() and require() respectively.
  2. There is no need to put the name of the module in your code. It is named implicitly based on where you put it in the views system.
  3. Return the value of the module instead of adding to a global variable.

2. Register your view as cacheable via simplecache**

In your plugin’s init function, just add:

 elgg_register_simplecache_view(‘js/my/module.js’); 

3. Use elgg_require_js to load the module on the current page

Calling elgg_require_js("my/module") tells Elgg to execute your module code on the current page. This is basically the asynchronous version of elgg_load_js. Note that elgg_load_js will not work with AMD modules!

Why AMD?

The reasons to choose AMD are plenteous and well-documented. Let’s highlight just a few of the most relevant reasons as they relate to Elgg specifically.

1. Simplified dependency management

No more “priority” or “location” arguments for your scripts. You don’t even need to call elgg_register_js for new AMD modules. They load asynchronously and execute as soon as their dependencies are available. Also, you don’t need to worry about explicitly loading your module’s dependencies using elgg_load_js. The AMD loader (RequireJS in this case) takes care of all that hassle for you. It’s also possible have text dependencies with the RequireJS text plugin, so client-side templating should be a breeze.

2. AMD works in all browsers. Today.

Elgg developers are already writing lots of Javascript. We know you want to write more. We cannot accept waiting 5-10 years for a native JS modules solution to be available in all browsers before we can organize our javascript in a maintainable way.

3. You do not need a build step to develop in AMD.

We like the edit-refresh cycle of web development. We wanted to make sure everyone developing on Elgg could continue experiencing that joy. Synchronous module formats like Closure or CommonJS just weren’t an option for us. But even though AMD doesn’t require a build step, it is still very build-friendly. Because of the define() wrapper, It’s possible to concatenate multiple modules into a single file and ship them all at once in a production environment.***

Conclusion

AMD is a battle-tested and well thought out module loading system for the web today. We’re very thankful for the work that has gone into it, and are excited to offer it as the standard solution for Javascript development in Elgg starting with Elgg 1.9.

We’d love it if some of you would install Elgg 1.9 from the master branch on GitHub and let us know what it’s like developing and managing AMD modules. We look forward to your feedback and questions!

* Despite the view file having a .php ending, you should not use PHP code in your modules. To get your syntax highlighter to highlight it as js, you can add // <script> as the first line of your file. Support for plain .js files is coming at some point in the future.

** We are looking into auto-registering js modules as cacheable so that you can skip this step entirely.

*** This is not currently supported by Elgg core, but we’ll be looking into it, since reducing round-trips is critical for a good first-view experience, especially on mobile devices.

  • * Despite the view file having a .php ending, you should not use PHP code in your modules.

    What about language translations inside js (like elgg_echo())?

  • No, you should not do that. Use the javascript equivalent instead: elgg.echo

  • Nice post, very informative, well thought out its exciting to see elgg moving forward. How difficult is it going to be to make the switch from 1.8 to 1.9 once its released, for the average elgger, anyway...I am guessing your not going to be able to just upgrade like before and simply replace files with new ones?  As for the database, will the current 1.8 database setup work with 1.9?

  • @Kimberly - there will be an upgrade path for 'average elggers' - you should test it first on a cloned installation though before you go straight to production.  Although the developers are making every effort to make sure that plugins should be mostly compatible, there's no guarantees and I'm guessing that most plugins will need *some* tweaks, though thankfully not outright rewrites.  In that case, if you're not a programmer you will probably want to wait a bit for plugins to fully catch up.

  • Makes alot of sense, thanks, I am most likely going to stick with 1.8 and not jump right into 1.9 until most of the tweaks are  made and things are caught up w/ all the plugins since I use so damn many, LoL.

Evan Winslow

Software Engineer at Google. Elgg enthusiast. I wrote the Javascript and CSS frameworks for 1.8.

Latest comments