Node.js Modules Header Mastering Node.js, Part 2 Eric W. Greene Microsoft Virtual Academy Header Mastering Node.js, Part 2 Node.js Modules Eric W. Greene Produced by
Course Overview Getting Started with Node.js Organizing Node.js Applications Overview of Module Systems CommonJS Format ES2015 Format Working with Babel Using CommonJS and ES2015 Modules
Getting Started with Node.js The course assumes some basic knowledge of Node.js and the JavaScript programming language To run the examples on your machine, you will need Node.js installed Node.js can be downloaded from here: https://nodejs.org/en/ Install version 6 or later If you do not understand the basics of these technologies, then watch the WintellectNOW course, Introduction to Node.js
Organizing Node.js Applications Typically, Node.js applications are purely JavaScript code Very small applications can be coded in a single file However, most applications should be divided into many files Each file is considered a module, and can be imported/required by other modules Modules can be bundled into packages which exist independent of the application being coded, and linked in with the Node.js Package Manager (NPM) (see WintellectNOW's course on Node.js Packages)
Overview of JavaScript Modules As originally envisioned in 1995, JavaScript was not implemented with a formal way of breaking an application into modules Over the years, JavaScript developers came up with two popular patterns for creating modules to isolate source code for reuse, and prevent polluting of the global namespace Asynchronous Module Definition (AMD) https://github.com/amdjs/amdjs-api/blob/master/AMD.md CommonJS http://www.commonjs.org
Asynchronous Module Definition (AMD) Modules Dynamically loads modules asynchronously as they are needed, and they are singletons Very popular for web applications because it reduces the bandwidth needed to load a web page because modules are only downloaded as needed Does not work well in a high latency or poor network environment as downloading the individual modules takes longer and can make the application feel sluggish to the user, or cause the application to fail altogether
Asynchronous Module Definition (AMD) Modules Not well suited for Node.js because Node.js applications run locally on a system, there is no downloading of JavaScript code from a server Common implementations of AMD are Require.js and Dojo
CommonJS Modules Synchronous, file-system based module system Modules are loaded off the file system as needed, the loading is synchronous (program execution blocks), and once the module has been processed, program execution continues Modules are loaded dynamically and they are singletons Node.js is the best example of a CommonJS implementation
ES2015 Modules The latest version of JavaScript, ES2015 (aka ES6), adds support for modules The modules are very similar to CommonJS, but cannot be used dynamically None of the JavaScript engines, including Node.js's V8 engine, supports the new module system To use the module system with Node.js, the Babel transpiler is needed Babel transpiles the ES2015 modules to CommonJS modules
ES2015 Modules To use the new module system with web applications a transpiler such as Babel needs to be combined with a packing tool such as Browserify or Webpack
System.js Dynamic Loader While importing ES2015 modules is static in nature, there is a growing consensus for a dynamic loader named System.js The dynamic loader would allow ES2015 modules to be dynamically loaded at runtime according to coding logic CommonJS and AMD are dynamic loaders which can follow static and dynamic programming patterns ES2015 modules are static only, System.js would fill this gap
Developing with CommonJS Modules The course will focus on CommonJS and ES2015 modules The basic idea is exporting and requiring/importing A module exports a value or an object, and another module requires that value or object When the exported object is a function object, it allows for a configuration to be passed into the module Behind the scenes, the module is wrapped inside a function, with parameters such as module, require, __dirname, and __filename
Building Your First Module
Configurable Modules Modules can return a function object which can be invoked with arguments which can configure the return value of the function While the module is the function object itself, the behavior of it allows the creation modules which can receive input parameters, and return a configured object The returned object from the function is NOT a singleton, the singleton is the function object itself, but in order to use the function object it must be invoked which is where the configurable behavior is available
Creating a Configurable Module
Destructuring Module Imports With CommonJS, the entire exports object is returned, there is no way to limit which exported parts are desired To filter out the exported parts which are not desired, ES2015 destructuring can be used Selective importing allows only the desired exports of a module to be imported instead of importing everything
Using Destructuring to Import Modules
Modules are Singletons Once a module is required, the module file is loaded, executed and the resulting object (or value) is the singleton result that is returned All future calls to require the module will return the original singleton result of the first require call The singleton pattern allows data to be shared between components of an application through the module system
Understanding the Singleton Pattern
Going Behind the Scenes Behind the scenes, CommonJS modules are wrapped in a JavaScript function The function has five named parameters: exports – points to the object which will exported module – the module object containing metadata about the module, the exports property of the module points to the object which will be exported require – the function used to require modules within the module
Going Behind the Scenes The function has five named parameters (continued): __dirname – the directory name of the folder the module's JavaScript source code file is located in __filename – the file name of the module's source code file
Going Behind the Scenes If module.exports is assigned to a new object, that new object will be returned Assigning a new object to module.exports does not update the exports variable to point to the new object; therefore, its less error prone to use module.exports instead of exports when setting up the object to be exported
Revealing the Wrapper Function
ES2015 Modules First official module system for JavaScript Inspired by AMD and CommonJS Not currently implemented in the JavaScript engines, but is available through transpilers such as Babel, Traceur Compiler, Rollup, and TypeScript
ES2015 Modules The built-in "destructuring" of ES2015 module imports allows the possibility of optimizing the source code distributes Exports from modules which are not used, could potentially be dropped from the final application's source code – commonly known a tree shaking
Babel Configuration Babel is a popular tool for transpiling ES2015 code to ES5.1 Babel is an extensible tool which supports a plugin architecture to transpile many languages to JavaScript such as JSX and RelayQL Babel can be used via a command line program or with plugins through tools such as Grunt, Gulp and WebPack For this course, Babel will be used to convert ES2015 modules to CommonJS TypeScript is another great tool which can transpile modules as well
Setting up Babel
Coding an ES2015 Module Using ES2015 modules requires one module to export something, and one module to import something Each file is considered a module, and the file importing from the exporting file must reference the exporting file via a relative path reference
Building Your First ES2015 Module
Exporting a Default Value/Object Using the export default keywords a module can be configured to have default export No "destructuring" is needed, the default value is imported and assigned to a variable When using default values with CommonJS, the exported default object is referenced via a default property on the export object
Default Exports
Exporting a Multiple Values/Objects Multiple export statements can be used to export multiple values and objects from the module Using destructuring, only the desired imports can be imported from the module
Aliasing Imported Values/Objects When export values and objects are imported, they can be renamed within the import statement via aliasing This allows imported values and objects to avoid name collisions with existing values and objects in the source code The as keyword is used to perform aliasing
Aliasing Imported Values/Objects
Conclusion Node.js applications can divided up into modules Modules are coded with the CommonJS module format, or with ES2015 modules when using a transpiler such as Babel or TypeScript Modules are singleton objects Configurable modules can be created by making the module a function object Using destructuring and aliasing the importer of the module has control over what is imported and what its named