Loading...

Node Modules

Lesson Plan

In this lesson we are going to go over modules in node. Our aim is to make our application as modular as possible, where our programming moto would be: Programming for the tomorrow. This means that we would like to split our program to chunks where different chunks can be reused throughout our app, and throughout future programs we will create. So this lesson we will talk about splitting our app to modules which are small reusable libraries of code, importing and exporting those modules, using external packages and using NPM.

What are modules

Modules are packages of code that you can reuse. Modules can consist of classes or functions arrays or objects or even primitives like strings. Modules consist of private members which can only be used in the own module and are not exposed outside of the module. Modules also consist of public members which can be used outside the module by importing the module we are building.

Our first module

Lets continue to hello world example that we completed in the previous lesson In the previous lesson we created an hello world script. If you didn't follow the previous lesson create a file called hello-world.js with the following code:

        
            console.log('hello world');
        
    

We want to turn this file into a module and wrap the console statement in a function. Whomever imports this module will be able to call a function that prints hello world on the screen.

Node treats every file as a module. which means that when node runs our hello world script it wraps the entire file with a function that looks like this:

        
            function(exports, require, module, __filename, __dirname) {
                // Module code actually lives in here
                console.log('hello world');
            }
        
    

This means that every variable declared with var/let/const will only be available in the current file, and unlike the browser where a variable declared with var can possibly find itself on the global scope, this won't happen in Node unless deliberetly attaching a variable to the global scrope. Lets go over the arguments of the wrapper function:

  • __dirname - absolute path of directory of current module
  • __filename - absolute path of the file of the current module
  • exports - you can attach properties here and they will be exported
  • module - module object of the current module
  • require - used to require modules

so to wrap a function around the console.log and export it outside of this file we can add it as a property to the exports. for example:

        exports.sayHello = function sayHello() {
            console.log('hello world');
        }
    

exports is a refrence to an empty object {} and this object will be exposed outside. There are cases where we prefer to export not an object and properties in that object, but rather we would like to export a class or a function. Lets say we want to export only the sayHello function and not an object. For this case we can use module.exports and assign it with what we want to export. change the hello world file to this:

        
            module.exports = function sayHello() {
                console.log('hello world');
            }
        
    

so the exports is just a short way for module.exports and we can assign module.exports a whole new value. Notice that doing something like this:

        
            exports = function sayHello() {
                console.log('hello world');
            }
        
    

is wrong and won't export our function since we are just changing the exports pointer to point at our function. Now lets try and import and use the module we created. Create another file called app.js we will use the require argument to import the module we just created, so add the following code.

        
            const sayHello = require('./hello-world');
            sayHello();
        
    

The require will take a string to the module we want to import. if the module is a file we created, we can place a relative string. the relative string is relative to the current app.js module. you can omit the extension if it's js.

Built in modules

Node has some built in modules compiled into its binary. To use them in our code we will have to require them. We won't go over all the built in modules, we will have an entire lesson about the most commonly used built in modules in node. For now we will just cover on importing those modules, specifically we will try to import the file system module (fs). We will import fs and try to read a file. first lets place a text file in our working directory:

        
            > echo "this text i want to read from file" > stam.txt
        
    

now change app.js to the following:

        
            const fs = require('fs');
            const path = require('path');
            const text  = fs.readFileSync(path.resolve(__dirname, 'stam.txt'));
            console.log(text.toString());
        
    

We are requiring tow built in modules one is for dealing with the file system, the other is path and contain utility functions for dealing with directories. fs.readFileSync reads a file and requires the absolute path of the file to read. path.resolve will create proper path by combining two path strings. we use __dirname for the full directory where app.js is located and append the name of the file we want to read.

Installing and using community packages

Node has a very large community and that community helped create a lot of open source modules which we can use. We can use the community packages and focus on developing the core of our app. This saves us a hell of a lot of development time, not to mention that there are a lot of packages that are heavily maintained and tested with very few bugs and a lot of contributers. We will use npm to install community package. additional info about npm will be added in another lesson, in this lesson we will cover basic installation and usage of community packages. In the project directory, init npm by typing:

        
            > npm init --yes
        
    

now install the following package:

        
            > npm install lodash --save
        
    

lodash is a utility library with many useful functions for manipulating data structures. Now lets try and use this library in our code. change the app.js to the following:

        
            const lodash = require('lodash');
            lodash.random(100)
        
    

This will create a random number between 0-100. npm installed the lodash package in the node_modules folder. when we require a package with no path it will look first in the global built in modules and then in the node_modules folder and then traverse back one folder and search the node_modules there and so on until it reaches the root folder.

Publishing your package

to publish your package modify the package.json file and add a main key which points to the js file that will be required. if there is no main key then node will look for an index.js file. through this file you can expose your library. you can't point to more files but the user can also import other files from your module by appending a path to the end with the filename he wants to import. After you set your package.json or index.js file, and also named your package in the package.json with a unique name and a version for your package, after that you are ready to publish with the command:

        
            > npm publish --registry <registry url>
        
    

We will cover more about publishing in the lesson about npm.

Summary

In this lesson we covered about node moduling system. It's an important lesson cause only if you know this topic well, will you understand how to turn your app to be more modular, and only by doing this will your code be reused in more places.