CHAPTER 2 ■ THE NODE MODULE SYSTEM
15
File Extension Processing
If require() does not find an exact match, it attempts to add .js, .json, and .node file extensions. As mentioned in
Chapter 1, .js files are interpreted as JavaScript source code, .json files are parsed as JSON source, and .node files are
treated as compiled add-on modules. If Node is still unable to find a match, an error is thrown.
It is also possible to programmatically add support for additional file extensions using the built-in require.extensions
object. Initially, this object contains three keys, .js, .json, and .node. Each key maps to a function that defines
how require() imports files of that type. By extending require.extensions, you can customize the behavior of
require(). For example, Listing 2-21 extends require.extensions such that .javascript files are treated as .js files.
Listing 2-21. Extending the require.extensions Object to Support Additional File Types
require.extensions[".javascript"] = require.extensions[".js"];
You can even add custom handlers. In Listing 2-22, .javascript files cause require() to print data about the
imported file to the console.
Listing 2-22. Adding a Custom Handler to the require.extensions Object
require.extensions[".javascript"] = function() {
console.log(arguments);
};
Caution ■ Though this feature has recently been deprecated, the module system API is locked, so require.extensions
is unlikely to ever disappear completely. The official documentation recommends wrapping non-JavaScript modules in
another Node program or compiling them to JavaScript a priori.
Resolving a Module Location
If you are interested only in learning where a package is located, use the require.resolve() function, which uses
the same mechanism as require() to locate modules. However, instead of actually loading the module, resolve()
only returns the path to the module. If the module name passed to resolve() is a core module, the module’s name
is returned. If the module is a file module, resolve() returns the module’s file name. If the Node cannot locate the
specified module, an error is thrown. The example in Listing 2-23 shows usage of resolve() in the REPL environment.
Listing 2-23. Locating the http Module Using require.resolve()
> require.resolve("http");
'http'
Module Caching
A file module that is loaded successfully is cached in the require.cache object. Subsequent imports of the same
module return the cached object. One caveat is that the resolved module path must be exactly the same. This is so
because a module is cached by its resolved path. Therefore, caching becomes a function of both the imported module
and the calling script. Let’s say your program depends on two modules, foo and bar. The first module, foo, has no
dependencies, but bar depends on foo. The resulting dependency hierarchy is shown in Listing 2-24. Assuming
that foo resides in the node_modules directory, it is loaded twice. The first load occurs when foo is resolved to the
your-project/node_modules/foo directory. The second load occurs when foo is referenced from bar and resolves to
your-project/node_modules/foo/node_modules.