Sunday, October 17, 2010

RequireJS 0.14.5 Released

RequireJS 0.14.5 is available for download. Primarily a bug fix for the first item below.
  • Fix bug where scripts were not loaded from the correct path. Did not affect RequireJS+jQuery builds, but affected other builds. If you do not use a RequireJS+jQuery build, then it is strongly recommended that you upgrade from 0.14.4 to 0.14.5.
  • Added an urlArgs config option to allow for cache busting when servers/browser misbehave during development.
I apologize for the quick series of releases this week. I should be slowing them down a bit now.

Saturday, October 16, 2010

RequireJS 0.14.4 Released, jQuery 1.4.3 support

RequireJS 0.14.4 is available for download. This release supports jQuery 1.4.3. What does this mean?
  • The bundled RequireJS+jQuery file on the download page has jQuery 1.4.3 in it.
  • Due to a change in jQuery, there are almost no patches to jQuery in the RequireJS+jQuery file, just a convenience patch to register it as a module.
  • If your scripts properly use define() with RequireJS, then it is possible to load jQuery from the Google CDN. This can save you some bandwidth costs!
There are a few caveats with using RequireJS to load jQuery from the CDN:
  • Most jQuery plugins assume jQuery is already loaded when they execute. However, with RequireJS, jQuery could still be loading when the plugin file executes. If you plan to use jQuery plugins in your project and you really want to load jQuery from the CDN, then in your own RequireJS-based project, you should wrap each of the plugins in a define(function(){ /*plugin goes here */ }); wrapper. Or, just stick with using the combined RequireJS+jQuery file served from your server.
  • If you use code with define() calls in them, be sure to do the minification and combining of scripts using the RequireJS optimization tool. It will make sure the define() calls get proper scripts names to allow all the scripts to be combined together. If you use another tool to just concatenate your define()'d scripts together, it will result in errors if the define()'d modules are not named. A copy of the optimization tool is included in the jQuery+RequireJS Sample Project.
  • This is only recommended if you have one version of jQuery loaded in the page.
An example showing how to configure RequireJS to load jQuery from the CDN:

require({
"paths": {
"jquery": "http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min"
}
});

//Now require jQuery when you want it, using 'jquery'
//as the dependency name.
//HOWEVER, note the important caveats above!

require(['jquery'], function ($) {
//...
});
Now if only I could get RequireJS releases on a CDN, that would be even sweeter!

Thursday, October 14, 2010

RequireJS 0.14.3 Released

RequireJS 0.14.3 is available for download.
  • Support for define(). It works the same as require.def(). It is supported in order to conform with the Asynchronous Module Proposal. require.def will continue to work, but you are encouraged to gradually migrate to define() for better compatibly with other Async Module loaders.
  • text! plugin now works in Node.
  • _dirname and _filename support in the r.js Node adapter.
  • Bug fix for priority option.
  • GPL license option removed: project is now just MIT and new BSD dual-licensed, since the new BSD license is compatible with the GPL.
The big motivation was the require.def() -> define() API change. I do not expect any more top-level changes to the API now, particularly when related to the Asynchronous Module proposal. There may be some API changes around how plugins are written at some point, but those are tricky to write today, and could use an API cleanup. However, using plugins in your application code will likely stay the same.

To be clear: require.def() will continue to be supported. If you only care about loading your modules via RequireJS, you can continue to use it. However, if you think you might want to allow your code to work in other script loaders that follow the Asynchronous Module API, then you should look at switching to define().

Tuesday, October 12, 2010

fn with no globals

This is a JavaScript sketch, please read the disclaimers.

Background


To get some decent code reuse, we need baseline support for loading code across environments. CommonJS made a good first pass with the Modules and Packages proposals. The Module one does not work well in the browser though, so I am hoping the Async Module proposal gains traction. Douglas Crockford likes async code loading too (around 39:10 in the video).

Relying on a server to generate client-friendly code is not a universal solution, and it is a particularly poor solution for doing mobile web development, where apps can be created with HTML/CSS/JS but run from the mobile device without a server.

RequireJS implements the Async Module proposal. There are some rough spots around the Packages proposal, particularly around mappings, but it is something that can be used, and I'm trying to support some version of packages with RequireJS.

The ECMAScript folks are looking at a Simple Modules spec, but it does not solve any of the problems for me. The problems have been addressed by RequireJS. It would be nice to not to have to include the code for RequireJS in an app, but it works, it is not crazy big, and it can always be pushed down to native environment support after it is broadly in use.

fn with no globals

What I would like to see instead of a Simple Modules is "fn". It is like "function" but it does not have access to the global space. You would use it just like "function" but any variables missing "var" would not be in the global space (could throw an error). If it needs a "use fn" or something like that, OK, but I am not familiar with when "use" strings are needed. Example:

fn hello() {
//the next line would throw
message = 'hello';

//the next line would be an error too
var name = window.name;

return message;
}
That would give me one of the big things out of Simple Modules that I cannot already have via RequireJS. It would also shorten the traditionally cumbersome "function" word and encourage good coding practice since it does not have access to the global scope. For situations that need global access, fall back to good old "function".

I would not be surprised if this has already been suggested, but as mentioned in my sketches preamble, just jotting down things as they come to me without doing due diligence.

Web Workers as Browser/Server Bridges

David Ascher and I had a discussion last week about server side JavaScript. He mentioned that while server side JavaScript would give some small incremental advantage, there would still be a split between what server devs needs and do and what browser devs need and do. Other people have made a similar observation.

Here is one sketch on what server side JavaScript could bring.

Server-side JavaScript

There are two ways to treat the browser and server workload split . One treats the browser as a dumb client, the other as a smart client.

1) Dumb client

Blogs, news sites, wikis. Content Management Systems (CMS). Serve HTML strings to a browser. There is likely some browser interactivity, but the sites can get by without it via progressive enhancement. The server is responsible for generating the HTML from data mashed together with templates.

This use case is well understood problem space. It is not always executed well, but it has been done many times. Having server side JavaScript will help with some sharing of code/design approaches with the browser, but that is about it. Still, for me it would be nice to have SSJS solutions for these cases.

2) Smart client

Servers as APIs/data stores. The server is doing straight-out business logic, data manipulation. The data sent to the browser is just in JSON, preferably not XML.

Server-side JavaScript is useful here given the expressiveness of the language: closures/anonymous functions for callbacks make using async easier to use, and Node's focus on an event loop is a great fit here, a more natural experience for a browser developer to help out with this area.

Using Servers as Web Workers

This an extension of #2. First, go read up on Web Workers. Short review:

var worker = new WebWorker('http://example.com/some/thing');

//Get messages from the worker
worker.onmessage = onMessageFunction;

//Get errors from the worker
worker.onerror = onErrorFunction;

//Post messages to the worker, only
//JSON-compliant messages back and forth
worker.postMessage({"msg": "hello"});

What would be ideal is that instead of running the web worker in the browser, it would do its work on the server. To bootstrap, a small JS shim could be used that runs in the browser that does the server communication to run the code on the server, and then a Web Worker environment/toolkit/library on the server needs to be created. This node-worker project might be a good place to start for the server code.

The important point: an app developer codes the logic on the server to the Web Worker environment, using postMessage to send out responses, onmessage and onerror to receive responses.

The neat thing about this approach: it can be used for simple request/response actions, or for longer term, comet-style long-lived messaging. It also could allow for actually running or mocking the server endpoint in the browser.

There needs to be some way to manage state. It would be nice to "pause" and "resume" a server-based web worker. Maybe that is just cookies, but it has to be secure to things like CSRF, and still give the user the ability to clear that state like they can clear cookies today.

The other nice thing about this model, it fits in with the event loop that JS developers use today, and it is a tightly constrained environment. No messing about with "requests" and "responses" in the traditional server sense.

There are probably concerns about what it does to a REST approach to API development. I am hoping that it just transforms the REST calls into events routed to web workers, not sure how that will shake out yet.

This is a JavaScript sketch, please read the disclaimers.

JavaScript Sketches

I have a few JavaScript-related things I want to talk about. I prefer implementing something or give a proposal more consideration before talking about it. However, I find that I end up not talking about a lot of things that bounce around in my head. So I will start talking more about them, even though they are not fully formed. This blog post is to set up the context and disclaimers for those posts, so I can link back to them.

Disclaimers

I will make a bunch of declarations that I will not back up as much as they deserve. I may expand on them in later posts, but most likely I will not. The point of these sketches is to get the basic thought out instead of keeping it internal.

If I cast a negative light on your favorite project, keep in mind this is my blog, so it is naturally biased, and there always needs to be hedge bets. Until there are implementations with real world use, the future is always malleable, and often big enough to accommodate a few different views. Keep working on what you are passionate about.

I will be ruthless and what may seem like unfair in my comment management/deletion policy. You are free to say your own piece on your own blog.

Who am I?

I have been working with JavaScript since at least 1998. It was earlier than that, but that was the start of a large scale project that got real users. Since then I have used it on and off. I still need to learn more about the inner dark places of the language and its implementations, but I have used it to build some larger front-ends, particularly while at AOL: a picture service UI, a cross-browser plugin for streaming radio, a chat service UI, and helped out with a webmail service UI. I contribute to Dojo, make RequireJS, and work at Mozilla on web-based messaging services. I only want to develop for the web platform, using JavaScript. I did not study computer science, but physics, so I lack some of the CS technical underpinnings.

Sunday, October 03, 2010

RequireJS 0.14.2 Released

RequireJS 0.14.2 is available for download. This is a bug fix release:
These issues affect use cases with traditional CommonJS modules/converted modules or with CommonJS packages. If you do not deal with those use cases, there is less urgency to upgrade.

I recently started using the RequireJS code in Node beyond simple tests, working on a Node-based package tool. Once I get it up an running, I'll post more on this blog. In the meantime, there is a design sketch, and some code, but it is very rough at the moment, mostly scaffolding.