Modules and npm

Date 09/09/2014

Node.js applications are JavaScript files that are run via node binary.

Scope in Node.js is file based, thus each file can be used as a self contained module. In case there are several files which are to be used together, one should be the main (as main() would be in languages like C) while others are modules exporting their functionality. In the tasks to be done below, the task-1.js is the main file for the first task.

The tasks done during this lecture should be saved in a GitHub repository called hello-node-js. Each file should be named in lowercase, starting with task-, followed by the task number and end with .js. Thus running a command node task-1.js would run the code created in the first task (and print out "Hello World").

  1. Create a "Hello World" application, an application that prints out the text "Hello World"

  2. Create an application that takes one numerical argument, doubles it and prints it

  3. Create an application that uses a module.

    • The module has one method

    • That method takes one parameter, a filename

    • That method returns the timestamp of the last modification time for the file if it exists. Else it should return false

    • The main part of the application should format the given timestamp to match Finnish date and time format

    • The result is finally printed out.

  4. Fork the repository of your classmate and create a pull request on their task 3, by doing the following changes:

    • Find an existing module from npmjs.com that can be used for formatting the timestamp

    • Replace the formatting functionality with one from the module found.

  5. Optional: Come up with a repetitive task that you might be doing every now and then, for example renaming files based on certain criteria, resizing images, trimming whitespace, etc.

    • Create an application that simplifies that work for you

    • Consider using .forEach at least once

    • Possibly use other programs installed via spawn.

  6. Optional: Extend the task 5 to be used as a module

    • Create package.json with required information and license of your choosing

    • Tag v0.1.0 release

    • Optional: publish it to npm.

Please note that in task 4, GitHub will take care of any naming collisions that might occur if the repositories have the same name.

Feel free to add any links below that were helpful for you when completing the above tasks, via pull requests.

Code examples

Task 1

Simply just using console.log() method prints out to the command prompt, as described in the relevant API documentation.

// task-1.js
var words = "Hello World";
console.log(words);

The string which is saved in the variable words, could also be written directly inside the console.log() call, but for the sake of maintainability and possibly further development it is better to use variables even for such a simple task.

Another option would be to use the util module. For example:

// task-1-util.js
var util = require('util');
var words = "Hello World";
util.puts(words);

Task 2

In order to get access on the command line arguments, use global process variable. It is also documented in the API documentation.

// task-2.js
var arg = process.argv[2];
console.log(arg * 2);

Run the given application node task-2.js 3. It should output 6.

The process.argv is an array of the command line arguments, starting with thenode at index 0. Therefore the index 2 contains the first argument given to the script, while the script filename is available at the index 1.

Task 3

Use the native module called fs for file system access.

// last-mod.js
var fs = require('fs');

module.exports = function(filename) {
    if (fs.existsSync(filename)) {
        var stat = fs.statSync(filename);
        return stat.mtime;
    }
    return false;
};

The above use synchronous method fs.statSync() returns a statistics object which provides the information needed in its mstat property.

It should be noted that the returned value was mistakenly assumed to be a timestamp (number of seconds from 1st January 1970), but it is in fact an instance of the JavaScript Date object.

Now the last-mod.js file can be used as a module, by requiring it in the same fashion as other modules. In order to make it clearer that it is in the same directory, the ./ is used.

The main file could look something similar as shown below. Note that the date formatting takes up most of the lines.

// task-3.js
var m = require('./last-mod');

var filename = process.argv[2];
var timestamp = m(filename);
if (timestamp !== false) {
    var date = timestamp;

    var fin = date.getDate() + '.' +
        (date.getMonth() + 1) + '.' +
        date.getFullYear();

    fin += '  ' + date.getHours() + '.' +
        date.getMinutes();

    console.log(fin);
}
else {
    console.log("Error message");
}

Task 4

Once the fork has been done at GitHub and cloned locally, package.json configuration file needs to be created, in order to define the required dependency.

npm init

The above command will ask few questions, such as name and version. It will create something similar to:

{
  "name": "Lecture-3",
  "version": "0.1.0",
  "description": "",
  "main": "task-3.js",
  "dependencies": {},
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT"
}

It is fine to ignore the error text in the test section. The testing subject will be discussed further in a later lecture.

Now the module need to be installed and saved to the dependency list. The following command does both of those:

npm install --save moment

Thus the package.json will be updated with the following information:

"dependencies": {
  "moment": "^2.8.3"
}

In order to take the moment module in to use, it needs to be imported with var moment = require('moment');. Now the module is available with momentvariable name and the date formatting can be simplified to a single line, such as moment(date).format('D.M.YYYY H.m');. Formatting options are described in detail at the moment module documentation.

Resulting updated main file would look something like shown below:

var m = require('./last-mod');
var moment = require('moment');

var filename = process.argv[2];
var timestamp = m(filename);
if (timestamp !== false) {
    var date = new Date(timestamp);

    var fin = moment(date).format('D.M.YYYY  H.m');

    console.log(fin);
}
else {
    console.log("Error message");
}

The modules downloaded from [npmjs.com][] are placed in a directory called node_modules. In most cases that folder should not be placed under version control, thus it should be ignored by Git. This can be achieved with the .gitignore file, which contains a list of files which will be ignored.

In this case the contents of .gitignore would look something similar to:

# Dependency directory
node_modules

The file .gitignore itself should be under version control. It can be created and added to the repository with these commands:

touch .gitignore
git add .gitignore

Last updated