JavaScript Module Conventions?

| 2 Comments

Unobtrusive JavaScript calls for JavaScript code to be removed from our HTML and placed in external .js files. At the same time, JavaScript frameworks and libraries are multiplying like crazy. More and more, we are going to be seeing web pages that load 2, 3, or more external .js files.

This means that we need to become disciplined about how we create those .js files, and adopt namespace conventions for these external modules of code so that two modules do not overwrite each others properties.

As far as I can tell, each JavaScript framework out there does this slightly differently. The most explicitly documented set of conventions I've seen are Casey West's rules for writing modules that work with his JSAN.use() function Casey's use() function is a perl-influenced function that loads (dynamically!) a .js module and then imports a set of symbols from the module into the global namespace. it is good stuff, but his module-structuring and namespace-creating rules are tied directly to his JSAN.use() code and I don't think they are general enough for people who want to write modules to be statically loaded with a <script> tag.. For example. a JSAN module defines the set of symbols that it can export, but the only way to import those symbols is via the use() function. There is not a separate import() function for importing symbols. without using use().

If you know of a well-articulated set of conventions for defining reusable modules of JS code, putting them in namespaces, and importing symbols, please add a comment to this post!

Here is my first cut at a list of requirements for a JavaScript module system:

  1. A .js module must not define more than one symbol in the global namespace. If it does define a symbol, that symbol should probably be the same as, or derived from, its filename.
  2. Any additional symbols defined by a module should be defined within a separate object, or "namespace".
  3. We need a way to selectively import symbols from a namespace into the global namespace. This is for convenience only; the methods deifned by a module should be written to work from their own namespace or from the global namespace.
    1. We could standardize an import() function for doing this importing. Or just create the necessary conventions, so that different frameworks can create their own import() methods.
    2. Modules should probably be allowed (but not required) to declare their own list of exported symbols (as JSAN modules do). And if such a list is defined, the import facility should not allow non-exported symbolsto be imported.
  4. For client-side programming, modules need a safe way to register code to be run in response to the onload event, without worrying that they will overwrite or be overwritten by the initialization code for some other module.
  5. There should be a standard way for a module to declare its name and version number.
  6. There should be a standard way for a module to register itself as loaded, and a standard way for a module to query the list of loaded modules (to verify that any modles it depends on are already present).

Please feel free to add your own ideas in the comments!

2 Comments

Most of what you want already exists in the JSAN master plan, it just hasn't appeared at the user side yet.

For example:

JSAN.import is coming to let you manually do the importing.

The onLoad one is tricky, since onLoads are terribly unreliable.

Module versioning, or at least class versioning is already specified using the Module.Name.VERSION variable.

And there is a standard way of registering, specifically inside the JSAN INC object, which is a rough equivalent of Perl's %INC hash (although to be more flexible, this works on a file basis, and not the module name).

As for the problem of loading dynamically, note that this represents 1 of the 6 modes for loading in modules, and represents the low hanging fruit.

There's a bunch of (for me) far more interesting modes on the way from JSAN::Librarian and friends.

Yeah, all of these, except 4, are already solved problems in JSAN (and dojo I believe).

To solve 4, you can just bring in a module that implements a call stack for onload (like MochiKit.DOM.addLoadEvent). I don't really think that it should be a problem that the module system needs to solve.

Books

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

Completely updated for Ajax and Web 2.0

"A must-have reference"
Brendan Eich,
creator of JavaScript

The classic Java quick-reference

Advertising

Pages

Hosted By

Powered by Movable Type 4.21-en