require()

Modul8's require() works hand in hand with a private define() call that gets pre-pended to the compiled source. On compilation each module is wrapped in a define call (ensuring encapsulation of private variables between modules) that give each of these modules the necessary context for the require() calls it may make. All context is stored via closures and will be hidden from you.

Ways to require

There are four different ways to use require:

File extensions

File extensions are never necessary, but you can (and sometimes should) include them for specificity (except for on the data domain).

To see why you perhaps should, consider the simplified algorithm require() uses to resolve the files you required on the server:

name = require input, domain = current domait (stored in closure)
while(domain)
  return true if exists(domain + name)
  return true if exists(domain + name + '.js')
  return true if exists(domain + name + '.coffee')
  domain = nextDomain
return false

If there is one thing to learn from it is is that you absolutely DO NOT omit extensions and keep .js and .coffee versions in the same folder or you will quickly become very frustrated as to why your coffee changes arent doing anything.

Require Priority

Requires are attempted resolved with the following priority:

if require string is relative
  resolve absolutized require string on current domain
else if require string includes domain prefix
  resolve require string on specified domain
else //arbiter search
  resolve require string on the M8 domain

if none of the above worked
  resolve on all other domains

//error

In other words, collisions should not occur unless you have duplicate files in different domains, and you are very relaxed about your domain specifiers or arbiter prefixes.

Hooking into define

modul8 defines way to help you attach objects/fn to certain domains both live on the client and from the server via data(). The API docs have full information on this.