Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Mastering Node.js

You're reading from   Mastering Node.js Expert techniques for building fast servers and scalable, real-time network applications with minimal effort

Arrow left icon
Product type Paperback
Published in Nov 2013
Publisher Packt
ISBN-13 9781782166320
Length 346 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Sandro Pasquali Sandro Pasquali
Author Profile Icon Sandro Pasquali
Sandro Pasquali
Arrow right icon
View More author details
Toc

Table of Contents (20) Chapters Close

Mastering Node.js
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
1. Understanding the Node Environment FREE CHAPTER 2. Understanding Asynchronous Event-Driven Programming 3. Streaming Data Across Nodes and Clients 4. Using Node to Access the Filesystem 5. Managing Many Simultaneous Client Connections 6. Creating Real-time Applications 7. Utilizing Multiple Processes 8. Scaling Your Application 9. Testing your Application Organizing Your Work Introducing the Path Framework Creating your own C++ Add-ons 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.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at £13.99/month. Cancel anytime
Visually different images