Monday, September 27, 2010

RequireJS 0.14.1 Released

RequireJS 0.14.1 is now available.

I just pushed a small update to fix three issues that dealt mostly with the new shortened anonymous module syntax used to wrap traditional CommonJS modules, and the converter tool for adding in the anonymous wrapper.

If you were using the regular RequireJS module format, with the dependencies specified outside the definition function, then you likely do not need to upgrade right away.

In fact, you may want to wait a couple days to see if there are any other updates. Given the newness of the anonymous module code and more people trying it with traditional CommonJS modules, I want to push out quicker releases to give those new users the best experience. I will be sure to mention if the update is recommended for all users.

There is one fix in this release for a type of deeply cyclic/circular dependency issue, but I believe it to be a rare issue for most current users. If 0.14.0 is working for you, then no need to try the latest version right away.

Sunday, September 26, 2010

RequireJS 0.14.0 Released

RequireJS 0.14.0 is now available. The big changes:
This is a significant release. Thanks to Kris Zyp for figuring out how to make anonymous modules work with IE, and to Tom Robinson for the suggestion to use Function.prototype.toString() to make converting traditional CommonJS modules easier.

The async module format/async require that is now supported by RequireJS really feels like it is the best of both worlds: something that is close enough to traditional CommonJS modules to allow those environments to support the format, while still having something that performs well and is easy to debug in the browser. I really hope the format can be natively supported in existing CommonJS engines. Until then, RequireJS works in Rhino and has an adapter for Node.

I put up a CommonJS Notes page for people coming from a CommonJS background. Also, the API docs are updated to reflect the simpler anonymous module format, and it includes a new section about loading modules from CommonJS packages.

What is next

Working with CommonJS packages has a few manual steps: finding the package, downloading it, configuring its location. I want to work on a command line package tool that makes this easy. Hopefully it will be able to talk to a server-side package registry too, to allow simpler package lookups by name (something like npm, but something that can house modules in a format used by RequireJS). Kris Zyp has already done some work in this area, and I hope to just use it outright for RequireJS, or leverage the code.

Once that lands, then it feels like it will be time for a RequireJS 1.0 release. The code has been very usable for a few releases now, but I have kept the release numbers below 1.0 to indicate that the final mix of features were being worked out. With the changes in this release, it feels like the major format changes have landed. For those of you who have used previous RequireJS releases, your code should still work fine, and it should work as-is in future releases too.

Monday, September 20, 2010

Anonymous Module Support in RequireJS

Thanks to the clever research and design feedback from Kris Zyp, I just finished committing some preliminary support for anonymous modules in RequireJS.

What are anonymous modules?

They are modules that do not declare their name as part of their definition. So instead of defining a module like so in RequireJS:

require.def('foo', ['bar'], function(bar) {});

You can now do this:

require.def(['bar'], function (bar) {});

When using RequireJS in the browser, the name of the module will be inferred by the script tag that loads it. For Rhino/Node, the module name is known at the time of the require.def call by the require() code, so those environments have an easier way to associate the module definition with the name.

Why is this important?

This allows your modules to be more portable -- if you change the directory structure of where a module is, there are fewer things that you need to change. You still may want to check module dependencies, but RequireJS now fully supports of relative module names, like "./bar" and "../bar", so by using those, it can help make your module more portable.

Requiring a module name in the module definition was also a notable objection that the CommonJS group had to the module format that RequireJS supports natively. By removing this objection, it gets easier to talk about unifying module formats across the groups.

To that end, there has been talk in the CommonJS group of an Asynchronous Module definition, something that allows the modules to work well in the browser without needing any server or client transforms. Some of the participants do not like the module format mentioned above, and prefer something that looks more like the existing CommonJS modules.

Tom Robinson put forward this suggestion:
require.def(function(require, exports, module) {
var foo = require("foo"),
bar = require("bar");
exports.someProp = "value";
and use Function.prototype.toString() to pull out the require calls and be sure to load them before executing the module's definition function. After doing some research, it seems like this approach could work for modules in development, and optimizations could be done for deployment that would add the module name and the dependencies outside the function.

So I also put support for the above syntax into RequireJS, in an attempt to get to an async module proposal in CommonJS that works for the the people that like the old, browser-unfriendly syntax and for the people like me that prefer a browser-friendly format I can code in source.

We still need to hash out the proposal more, but I am hopeful we can find a good middle ground. I also hope the above syntax makes it easier to support setting the module export value via "return" instead of having to use "module.exports =" or "module.setExports()".

I still plan to support the syntax that RequireJS has supported in the past -- any of this new syntax will hopefully be additive.

What is the fine print?

Only one anonymous module can be in a file. This should not be a problem, since you are encouraged to only put one module in a file for your source code.

The RequireJS optimization tool can group modules together into an optimized file, and it has the smarts to also inject the module name at that time, so you get less typing and a more robust module source form, but still get the optimization benefits for deployment.

In addition to adding the module name, the RequireJS optimization tool will also pull out the dependencies that are specified using the CommonJS Asynchronous Module proposal mentioned above, and add those to the require.def call to make that form more efficient.

When will it be available?

Right now the code is in the master branch. Feel free to pull it and try it. There may be some loose ends to clean up, but there are unit tests for it, and the old unit tests pass.

This code will likely be part of a 0.14 release. I want to get in loading modules from CommonJS-formatted packages before I do the 0.14 release, so it still is probably a few weeks away. But please feel free to try out the latest code in master to get an early preview.

Again, many thanks to Kris Zyp for seeing patterns I overlooked, doing some great IE research, and for pushing for these changes.

Saturday, September 11, 2010

RequireJS 0.13.0 Released

RequireJS 0.13.0 is available! The changes:
Some bigger changes are in store for the next release. Kris Zyp has observed a pattern that may allow supporting "anonymous" require.def() module definitions, allowing modules to be more robust to path changes without requiring file editing. I want to get that to work, as well as support for CommonJS-style packages.