NML Says

Node.js and npm, First Steps

References for this Part

node.js official website

It has learning material as well as the canonical documentation.

npm Official documentation.

Jonathan Wexler. Get Programming with Node.js, Manning, 2019

Flavio Copes. The Node.js Handbook, Flavio Copes, 2018

node

Assuming that you have already installed Node.js, let us dive in at the deep end first. Somewhere on your hard drive, you create a project folder, and navigate to that folder with cd.

Write a file eg servera.js:

Example 1. <mydir>/servera.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer(function (req, res) {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain; charset=utf-8');   // no encoding
  res.end('Hello World!\nBlåbærgrød\n');
});

server.listen(port, hostname, function () {
  console.log(`Server running at http://${hostname}:${port}/`);
});

When the file is saved in your project folder. You issue the following command on the CLI:

1
node server.js

or, if you are lazy

1
node servera

Please notice its response on the command line. Then go to your browser, and navigate to: (http://localhost:3000) and check its content.

This is amazing. A webserver in 14, well really only 11, lines of code. This is what we shall work with if web programming is our endeavour. In Node.js we do not use a generic web server. We build our own project specific servers.

From the Top

After this shockingly easy step, let us take some baby steps aimed at getting to know node from the basics.

In some project directory write a file:

Example 2. <somedir>/js0.js
1
2
3
4
5
6
7
8
9
'use strict';
let marr = ["abc", "def", "ghi"];

let printNumbers = function (arr) {
    for (let elm of marr)
        console.log(elm);
}

printNumbers(marr);

then run it by

1
$ node js0

resulting in

1
2
3
4
5
$ node js0
abc
def
ghi
$

You may also do programming experiments live by executing node interactively

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ node
Welcome to Node.js v15.6.0.
Type ".help" for more information.
> console.log('hello, World!');
hello, World!
undefined
> let arr = ['abc' 'def', 'ghi'];
undefined
> for (let elm of arr)
... console.log(elm);
abc
def
ghi
undefined
>
(To exit, press Ctrl+C again or Ctrl+D or type .exit)
>
$

Generally you should never start any program on your computer befor you know how to exit from it. You exit the node interpreter by issuing one of

It is obviously easier in the long run to create js files in an editor and the running them as already shown above.

Working interactively you may load js files into the interpreter with a .load <filename> command, and you may save your interactive work with a .save <filename> command.

Modules in node

In programming we use modules as a means of storing generalized code as modules thereby making this code available for import wherever needed. In node the import construct, as known in browser based JavaScript is called require, and the usage is slightly different.

Try this:

Example 3. First Module: messages.js
1
2
3
4
5
6
7
8
"use strict";
// no const, var or let before exports. 
// exports is an already defined object
exports.messages = [
    "A program a day makes the doc go away.",
    "You can do it!",
    "Yes you can!"
];

Usage:

Example 4. Using the Module, printMessages.js
1
2
3
4
const msgMod = require("./messagesm");  // look mum, no .js
msgMod.messages.forEach(function (msg) {
    console.log(msg);
});

Execution:

1
2
3
4
$ node printMessages
A program a day makes the doc go away.
You can do it!
Yes you can!

Modules are self contained JavaScript files containing code that pertains to a single concept, functionality, or library. (Wexler, 2019)

We create them in order to use them in more than one context. As such they are a manifestation of the DRY principle. If you think of frontend JavaScript in the browser, yes, they are very similar to modules handled by import, but beware of the syntax differences. See also (Copes, 2019 pp 43-44).

Syntactical Variations of Export

The following contains some variations in writing modules and the use of them. The choice is yours. You’re the programmer.

Example 5. First Variant
1
2
3
4
5
6
7
exports.circArea = function (r) {
    return Math.PI * r * r;
}

exports.circCircumference = function (r) {
    return 2 * Math.PI * r;
}

Usage:

1
2
3
4
const mod = require("./messagesm1");    // look mum, no .js

console.log(mod.circArea(4));
console.log(mod.circCircumference(4));
Example 6. Second Variant
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const circArea = function (r) {
    return Math.PI * r * r;
}

const circCircumference = function (r) {
    return 2 * Math.PI * r;
}

exports.circArea = circArea;
exports.circCircumference = circCircumference;

Usage:

1
2
3
4
const mod = require("./messagesm2");    // look mum, no .js

console.log(mod.circArea(4));
console.log(mod.circCircumference(4));
Example 7: Third Variant
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let MyMath = {
    circArea: function (r) {
        return Math.PI * r * r;
    },

    circCircumference: function (r) {
        return 2 * Math.PI * r;
    }
}
exports.MyMath = MyMath;

Usage:

1
2
3
4
const mod = require("./messagesm3");    // look mum, no .js

console.log(mod.MyMath.circArea(4));
console.log(mod.MyMath.circCircumference(4));
Example 8. Fourth Variant
1
2
3
4
5
6
7
8
9
module.exports = {
    circArea: function (r) {
        return Math.PI * r * r;
    },

    circCircumference: function (r) {
        return 2 * Math.PI * r;
    }
}

Usage:

1
2
3
4
const MyMath = require("./messagesm4"); // look mum, no .js

console.log(MyMath.circArea(4));
console.log(MyMath.circCircumference(4));

The difference is really only aesthetic. The result in all four cases:

1
2
3
$ node mathMod1
50.26548245743669
25.132741228718345

npm

The npm documentation is found at (https://docs.npmjs.com)

atly, that the “Node.js package ecosystem is the world’s largest ecosystem of open source online libraries”. (https://nodejsera.com/nodejs-tutorial-day7-all-about-npm.html) is a good video about it. npm is often installed automatically when you install node. If it does not respond to the following, install it. It is essential that we’re always using the latest version of this software. Check your version with

1
$ npm -v

To get the latest you might update via your package manager, npm itself.

1
$ npm install npm@latest -g

The g flag makes it a global install meaning it is not for the current project only.

npm Commands

The npm commands needed at this preliminary stage are

npm init
This command create a project description file containing various configuration parameters,
npm set
Sets up certain defaults used by npm init.
npm install
Installs a package from the npm repository.
npm update
Updates packages of the project.
npm outdated
Tells you whether some packages need to be updated.
npm uninstall
Removes packages if no longer needed.

npm init

When we work with node we need to keep track on the files needed for the current project and package.json helps us with that. It is interactively created with npm init

Example 9. Interactive npm init
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (nmltest)
version: (1.0.0)
description: Demo test
entry point: (index.js)
test command:
git repository:
keywords:
author: @phidip
license: (ISC)
About to write to /home/nml/nodeProjects/nodejsexps/nmltest/package.json:

{
  "name": "nmltest",
  "version": "1.0.0",
  "description": "Demo test",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "@phidip",
  "license": "ISC"
}


Is this OK? (yes) 

It is non-interactively done as follows. This is based on some configurable best practices parameters.

Example 10. Automatic npm init
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ npm init -y
Wrote to /home/nml/nodeProjects/nodejsexps/package.json:

{
  "name": "nodejsexps",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Just like that, no questions asked. The generated file package.json may be edited and adapted in either case. In a bit we shall see an example of just that.

npm set

You may remember from ancient history when you first started using git, you supplied some useful configuration parameters such as your name and email address. npm offers a similar feature. This is a one time effort.

Example 11. npm set
1
2
3
4
5
$ npm config set init-author-name "Niels Müller Larsen"
$ npm config set init-author-email "nmla@iba.dk"
$ npm config set init-author-url "http://dkexit.eu"
$ npm config set init-license "MIT"
$ npm config set init-version "0.9.9"

having done that let us try re-issuing the npm init -y

Example 12. Result of Automated npm init
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ init -y  
Wrote to /home/nml/exercises/ds3/package.json:

{
  "name": "ds3",
  "version": "0.9.9",
  "main": "runme.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "Niels Müller Larsen <nmla@iba.dk> (http://dkexit.eu/)",
  "license": "MIT",
  "description": ""
}
$

npm install

If we install an npm module in our project eg

Example 13. npm install <package>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
$ npm install bcryptjs
added 1 package, and audited 2 packages in 711ms

found 0 vulnerabilities
$ cat package.json
{
  "name": "ds3",
  "version": "0.9.9",
  "main": "runme.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "Niels Müller Larsen <nmla@iba.dk> (http://dkexit.eu/)",
  "license": "MIT",
  "description": "",
  "dependencies": {
    "bcryptjs": "^2.4.3"
  }
}

We see in the edited package.json that a dependencies section has been added, this is done by npm install. This section is used by npm install (no parameters.)

Example 14. npm install
1
$ npm install

installs or updates the modules needed for the project. Those modules are kept in the directory node_modules which is created by the first execution of npm install. If, for some reason, this directory is deleted, it is recreated just by running npm install again. It is normal procedure to run npm install as the first step of each test of the project.

A package name such as bcryptjs may be suffixed meaning that the npm install bcryptjs@2.4.3 will install exactly that version whereas npm install bcryptjs^2.0.0 means that the latest version 2 variant will be installed.

npm update

Example 15. npm update
1
$ npm update

in the project folder will update all packages.

npm outdated

Example 16. npm outdated
1
$ npm outdated

will reveal the necessity of an update. Just after an update, its output should, of course, be empty.

npm uninstall

Example 17. npm uninstall
1
$ npm uninstall <packagename>

removes a package.

On all these commands a global flag, -g or --global is applicable here. Global means that the action will concern all projects, not just the project in the current directory.