Skip to content

Latest commit

 

History

History
11 lines (6 loc) · 3.27 KB

history.md

File metadata and controls

11 lines (6 loc) · 3.27 KB

RequireJS History

I work a lot on the Dojo Loader. The normal dojo loader uses synchronous XMLHttpRequest (XHR) calls. However, the XHR loader cannot load Dojo modules from other domains because of the same-origin restrictions. So I created the xdomain loader that required a build step to inject function wrappers similar to what RequireJS uses, but more complex, due to i18n bundle loading and dojo.requireIf behavior. Because of the more complex i18n and requireIf requirements and the existence of many dojo modules already out in the world, I did not feel like the Dojo community would consider writing modules with function wrappers manually.

However, the sync XHR loader has other issues, like making debugging harder. In 2009, David Mark suggested that Dojo use document.write() to load modules before the page loads to help with that issue, but that means required dependencies would not load until after the current module executes. This can cause errors if the module references a dependency as part of the module's definition. So a function wrapper is needed. The Dojo community seemed more amenable to considering a function wrapper, particularly since we are considering a Dojo 2.0 that can break some APIs. I fleshed out some of the details for RequireJS on the dojo-contributors list, and Mike Wilson originally pushed for a more generic loader that could load plain files as well as allow for different contexts. It is likely RequireJS will be used for any Dojo 2.0 effort.

YUI 3's use() function is also very similar to require, and use()'s API (but not code) also informed require's structure. I believe RequireJS is more generic, since YUI seems to use labels for their modules that do not directly correspond to file paths. It also looks like it cannot load plain JS files, and I liked explicitly passing the dependent modules as arguments to the function definition. YUI.use() might support some of these features underneath, but I just looked at the top-level API doc.

I originally wanted something that would work with CommonJS modules, but those modules seem to be structured assuming a synchronous module loader, which is possible in server-side JavaScript environments. However, I am mostly concerned with something that works well in the browser, and that means needing a function wrapper so we can use script tags. Using synchronous XHR is not very friendly for new developers or people who want easy of debugging across browsers. It can also be slower than plain script tag loading. Some environments, like Adobe AIR do not allow eval() and most developers are taught that eval() is evil and should be avoided.

I created the seeds of RequireJS as RunJS. As I tried to get more in sync with CommonJS modules to allow more code reuse, I proposed CommonJS Transport/C proposal. The transport format allows mapping traditional CommonJS modules to a format that works best in the browser. I then converted the RunJS code to RequireJS to match the API in the Transport/C proposal. There is a conversion script to convert CommonJS modules to the format that RequireJS understands. While that script does basic module conversion, it may not work for all modules, and some modules do not make sense to run in a browser environment.