edx/edx-platform — pull request #662 by singingwolfboy (2013-08-13 16:20:51+00:00)
Title: requirejs in Studio

This branch properly integrates [requirejs](http://www.requirejs.org/) into the Studio codebase. Although Studio appears to work, this branch is not yet ready to be merged: the Jasmine tests will need to have their environment reconfigured, and are currently disabled. Lettuce tests can and do run just fine, but there are one or two remaining Lettuce test failures that I haven't yet hunted down and fixed (I need to move on to other work). This pull request is intended to spark discussion and to serve as an example for how we can use requirejs, especially in the development of XBlocks.

Requirejs does away with attaching Javascript functions and classes to a global namespace, and instead forces JS files to declare their dependencies at the top of the file. For example, if a file uses jQuery, it will start with `require(["jquery"], function($) {` -- you can see that rather than jQuery being bound to the global `$` variable, it's passed into the file as a local `$` variable. It's a convention that works surprisingly well, and although this pull request has a lot of code changes, most of them were pretty simple and quick to implement.

We can also use requirejs as an optimizer, loading together requirements bundles before the code goes into production so that any given page only needs to dynamically load one JS file -- and that JS file will contain only the code that the page needs. Requirejs also allows for easier unit testing, since you can load and test a given file in isolation. Requirejs also enforces a more modular coding style, requiring only one JS class per file, and encouraging an understandable file layout in the project.

Caveats in this pull request: this PR is focused on the Studio code, and I haven't tested this with the LMS at all -- there are a few files outside of the `cms` namespace that I had to touch, but I figured that we can deal with the fallout of that if and when we decide to move forward with this approach. In addition, due to the way that XModule dynamically assigns arbitrary MD5-based names to its JS files, the XModule JS is currently incompatible with requirejs. I've created a wrapper script around all the XModule JS files, so that when any other script requires the XModule JS, *all* the XModule JS files are dynamically loaded.

Please review the code, comment, ask questions, and learn about how requirejs works -- it's generally considered to be an excellent pattern for managing a large amount of Javascript.