Book Image

Mastering Node.js

By : Sandro Pasquali
Book Image

Mastering Node.js

By: Sandro Pasquali

Overview of this book

Node.js is a modern development stack focused on providing an easy way to build scalable network software. Backed by a growing number of large companies and a rapidly increasing developer base, Node is revolutionizing the way that software is being built today. Powered by Google's V8 engine and built out of C++ modules, this is a JavaScript environment for the enterprise.Mastering Node.js will take the reader deep into this exciting development environment. Beginning with a comprehensive breakdown of its innovative non-blocking evented design, Node's structure is explained in detail, laying out how its blazingly fast I/O performance simplifies the creation of fast servers, scalable architectures, and responsive web applications.Mastering Node.js takes you through a concise yet thorough tour of Node's innovative evented non-blocking design, showing you how to build professional applications with the help of detailed examples.Learn how to integrate your applications with Facebook and Twitter, Amazon and Google, creating social apps and programs reaching thousands of collaborators on the cloud. See how the Express and Path frameworks make the creation of professional web applications painless. Set up one, two, or an entire server cluster with just a few lines of code, ready to scale as soon as you're ready to launch. Move data seamlessly between databases and file systems, between clients, and across network protocols, using a beautifully designed, consistent, and predictable set of tools.Mastering Node.js contains all of the examples and explanations you'll need to build applications in a short amount of time and at a low cost, running on a scale and speed that would have been nearly impossible just a few years ago.
Table of Contents (20 chapters)
Mastering Node.js
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Loading and using modules


The Node designers believe that most modules should be developed in userland—by developers, for developers. Such an effort is made to limit the growth of the standard library. Node's standard library contains the following short list of modules:

Network and I/O

Strings and Buffers

Utilities

TTY

UDP/Datagram

HTTP

HTTPS

Net

DNS

TLS/SSL

Readline

FileSystem

Path

Buffer

Url

StringDecoder

QueryString

Utilities

VM

Readline

Domain

Console

Assert

Encryption and Compression

Environment

Events and Streams

ZLIB

Crypto

PunyCode

Process

OS

Modules

Child Processes

Cluster

Events

Stream

Modules are loaded via the global require statement, which accepts the module name or path as a single argument. You are encouraged to augment the module ecosystem by creating new modules or new combinations of modules.

The module system itself is implemented in the require (module) module.

Understanding the module object

A Node module is simply a JavaScript file expected to assign a useful value to the module.exports property:

module.exports = new function() {
  this.it = function(it) {
    console.log(it);
  }
}

We now have a module that can be required by another file. If this module was defined in the file ./say.js, the following is one way to use it:

var say = require("./say");
say.it("Hello");
// Hello

Note how it was not necessary to use the .js suffix. We'll discuss how Node resolves paths shortly.

Note

Node's core modules are also defined using the standard module.exports pattern, as can be seen by browsing the source code defining console: https://github.com/joyent/node/blob/master/lib/console.js.

Once loaded, modules are cached based on their resolved filename, resolved relative to the calling module. Subsequent calls to require(./myModule) will return identical (cached) objects. Note however that accessing the same module via a different relative path (such as ../../myModule) will return a different object—think of the cache being keyed by relative module paths.

A snapshot of the current cache can be fetched via require('module')._cache).

The module object itself contains several useful readable properties, such as:

  • module.filename: The name of the file defining this module.

  • module.loaded: Whether the module is in process of loading. Boolean true if loaded.

  • module.parent: The module that required this module, if any.

  • module.children: The modules required by this module, if any.

Note

You can determine if a module is being executed directly via node module.js or via require('./module.js') by checking if require.main === module, which will return true in the former case.

Resolving module paths

The require statement is regularly seen when browsing (or building) a Node program. You will have noticed that the argument passed to require can take many forms, such as the name of a core module or a file path.

The following pseudo code, taken from the Node documentation, is an ordered description of the steps taken when resolving module paths:

require(X) from module at path Y
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.node is a file, load X.node as binary addon.  STOP
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
2. If X/index.js is a file, load X/index.js as JavaScript text.  STOP
3. If X/index.node is a file, load X/index.node as binary addon.  STOP
LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_AS_FILE(DIR/X)
   b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let ROOT = index of first instance of "node_modules" in PARTS, or 0
3. let I = count of PARTS - 1
4. let DIRS = []
5. while I > ROOT,
   a. if PARTS[I] = "node_modules" CONTINUE
   c. DIR = path join(PARTS[0 .. I] + "node_modules")
   b. DIRS = DIRS + DIR
   c. let I = I - 1
6. return DIRS

File paths may be absolute or relative. Note that local relative paths will not be implicitly resolved and must be stated. For example, if you would like to require the file myModule.js from the current directory it is necessary to at least prepend ./ to the file name in order to reference the current working directory—require('myModule.js') will not work. Node will assume you are referring to either a core module or a module found in the./node_modules folder. If neither exists, a MODULE_NOT_FOUND error will be thrown.

As seen in the pseudo code above, this node_modules lookup ascends a directory tree beginning from the resolved path of the calling module or file. For example, if the file at '/user/home/sandro/project.js' called require('library.js'), then Node would seek in the following order:

/user/home/sandro/node_modules/library.js
/user/home/node_modules/library.js
/user/node_modules/library.js
/node_modules/library.js

Organizing your files and/or modules into directories is always a good idea. Usefully, Node allows modules to be referenced through their containing folder, in two ways. Given a directory, Node will first try to find a package.json file in that directory, alternatively seeking for an index.js file. We will discuss the use of the package.json files in the next section. Here we need to simply point out that if require is passed the directory ./myModule it will look for is ./myModule/index.js.

Note

If you've set the NODE_PATH environment variable then Node will use that path information to do further searches if a requested module is not found via normal channels. For historical reasons $HOME/.node_modules, $HOME/.node_libraries, and $PREFIX/lib/node will also be searched. $HOME represents a user's home directory, and $PREFIX will normally be the location Node was installed to.