Alternative

node.js and npm on Mac OS

Date: 09.10.2019

Author: Patrick Rottländer

In this Article the installation and the use of node.js and npm is described. Node is a server side programming language to run JavaScript Code on a server and outside the browser. With node a developer can create server side programs in Java Script. npm is the node package manager to install node packages and modules. npm has more than 700.000 packages in its repository.

This article can also be read in pdf format.

node.js (or simply node) basically is a server side programming language to run JavaScript Code outside the browser. With node a developer can create server side programs in Java Script.

node contain various modules directly compiled into the node package like modules to access the network in asynchrons mode or modules to access the file system. Furthermore other modules can be embedded. These are precompiled files with .node extension or JavaScript modules. To manage these modules for node the node package manager (npm) exist. The npm package repository has more than 700.000 packages that can be installed with the npm package manager.

Installation of node and npm

node can be installed on a Mac with homebrew. node comes with npm.

Before node can be installed it must be checked if xcode command line tools are installed on the system.

Macbook Pro:~ user$ xcode-select -p
/Library/Developer/CommandLineTools
Macbook Pro:~ user$

The above command return that xcode command line tools are installed on your Mac and show the directory path where xcode command line tools are installed.

In case xcode command line tools are not installed run the following command in shell:

Macbook Pro:~ user$ xcode-select --install

Then it must be checked if Homebrew is installed.

Macbook Pro:~ user$ brew --version
Homebrew 1.7.7
Homebrew/homebrew-core (git revision 45d56; last commit 2018-10-08)
Homebrew/homebrew-cask (git revision 33e4d; last commit 2018-10-09)
Macbook Pro:~ user$

The above output show Homebrew 1.7.7 is installed on the Mac. In case Homebrew is not istalled so far run the follwoing command from shell:

Macbook Pro:~ user$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Check the Homebrew installation.

Macbook Pro:~ user$ brew doctor
Your system is ready to brew.
Macbook Pro:~ user$

To start with the node installation run the following command from shell:

Macbook Pro:~ user$ brew install node

After installation Homebrew created symlinks for node and npm in /usr/local/bin and symlink to the location where the relevant binaries have been installed.

Patricks-Macbook Pro:~ patrick$ ls -l /usr/local/bin
total 8

....

lrwxr-xr-x  1 patrick  admin   30  5 Jun 09:04 node -> ../Cellar/node/14.4.0/bin/node
lrwxr-xr-x  1 patrick  admin   38  5 Jun 14:22 npm -> ../lib/node_modules/npm/bin/npm-cli.js

....

We see that node has been installed in

/usr/local/Cellar/node/14.4.0/bin/node

and npm has been installed in

/usr/local/lib/node_modules/npm/bin

npm package management

npm install software packages always in node_modules directory. If you have not installed any software oackages with npm so far this directory does not exist and will be created during the installation process.

The installation of a software package with npm will be started with the following command.

npm install <package>

You can install software packages as Global Software Packages or as Local Software Packages.

Global Software Packages

If you want to use a software not only within a specific project but in global context on your machine then you provide the -g option in the install command.

npm install -g <package>

Then npm install this package in a global node_modules directory.

{prefix}/lib/node_modules

The prefix can be determined as follows

Macbook Pro:~ user$ npm config get prefix
/usr/local
Macbook Pro:~ user$

On my machine all global packages are installed under

/usr/local/lib/node_modules

To list all installed global packages on your machine you can ls -l the global node_modules directory.

Patricks-Macbook Pro:~ patrick$ ls -l /usr/local/lib/node_modules
total 0
drwxr-xr-x  24 patrick  admin  768  5 Jun 14:22 npm
drwxr-xr-x  21 patrick  admin  672  5 Jun 14:21 pm2

You can also list all global packages with the npm command.

Macbook Pro:~ user$ npm list -g --depth=0
/usr/local/lib
├── firebase-tools@5.0.1
└── npm@6.4.1
Macbook Pro:~ user$

To maintain your global packages run the following commands.

Check for outdated global packages

npm outdated -g --depth=0

Update a specific global package

npm update -g <package>

Update all global packages

npm update -g

Local Software Packages

Local Software Packages are dependencies of a node project. This mean these software packages are required by the project code to run correctly.

If you want to use a software package only in the context of a node project then you create a separate project subfolder on your system and change to this subfolder with cd. Any software package that will be installed under this subfolder is a dependency of your node project.

Patricks-Macbook Pro:test patrick$ pwd
/Users/patrick/Software/dev/node/test

Patricks-Macbook Pro:test patrick$ cd mytestproject

Patricks-Macbook Pro:mytestproject patrick$ pwd
/Users/patrick/Software/dev/node/test/mytestproject

Patricks-Macbook Pro:mytestproject patrick$ 

Now you are in the mytestproject application root directory. Run the command npm init from the application root directory.

Patricks-Macbook Pro:mytestproject patrick$ 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 init` 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: (mytestproject) 
version: (1.0.0) 
description: This is my Test Project
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: Patrick Rottlaender
license: (ISC) 
About to write to /Users/patrick/Software/dev/node/test/mytestproject/package.json:

{
  "name": "mytestproject",
  "version": "1.0.0",
  "description": "This is my Test Project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Patrick Rottlaender",
  "license": "ISC"
}


Is this OK? (yes) yes
Patricks-Macbook Pro:mytestproject patrick$ ls -l
total 8
-rw-r--r--  1 patrick  staff  251 14 Jun 08:58 package.json

Patricks-Macbook Pro:mytestproject patrick$

A package.json file has been created in your application root directory. This package.json file contain meta data about your project. Now we create the index.js file as our main application file for the project.

You can name the main application file as you like. It is only important that under "main" in the package.json file the file name match with the main application file name in your project root directory.

Patricks-Macbook Pro:mytestproject patrick$ touch index.js

Patricks-Macbook Pro:mytestproject patrick$ ls -l
total 8
-rw-r--r--  1 patrick  staff    0 14 Jun 09:08 index.js
-rw-r--r--  1 patrick  staff  251 14 Jun 08:58 package.json

Patricks-Macbook Pro:mytestproject patrick$

Dependencies are installed as local packages from a project root directory running the following command.

npm install <package_name> --save

npm will then create a node_modules directory under your project root directory and install the local packages there (incl. the dependencies of this new local package if there are any). npm will also create a package-lock.json file containing the current complete directory tree of all dependencies.

The package.json file is adapted and the new local software package is entered there as a dependency.

I have taken the following example 1:1 from the website of Tanja Rascia. If you want to read more details pls. go to Tanjas website.

Patricks-Macbook Pro:mytestproject patrick$ npm install left-pad --save

npm WARN deprecated left-pad@1.3.0: use String.prototype.padStart()
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN mytestproject@1.0.0 No repository field.

+ left-pad@1.3.0
added 1 package from 1 contributor and audited 1 package in 0.974s
found 0 vulnerabilities

Patricks-Macbook Pro:mytestproject patrick$ ls -l
total 16
-rw-r--r--  1 patrick  staff    0 14 Jun 09:08 index.js
drwxr-xr-x  3 patrick  staff   96 14 Jun 09:27 node_modules
-rw-r--r--  1 patrick  staff  366 14 Jun 09:27 package-lock.json
-rw-r--r--  1 patrick  staff  301 14 Jun 09:27 package.json

Patricks-Macbook Pro:mytestproject patrick$ cat package.json
{
  "name": "mytestproject",
  "version": "1.0.0",
  "description": "This is my Test Project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Patrick Rottlaender",
  "license": "ISC",
  "dependencies": {
    "left-pad": "^1.3.0"
  }
}
Patricks-Macbook Pro:mytestproject patrick$ 

After this we can write the code in index.js and use the functionality of left-pad. Therefore we must require the dependency at the beginning of the code.

// index.js

const leftPad = require('left-pad') // Require left pad
const output = leftPad('Hello, World!', 15) // Define output

// Send output to the console
console.log(output)

We run the programm using the following command and get the output on the console.

Patricks-Macbook Pro:mytestproject patrick$ node index.js
  Hello, World!
Patricks-Macbook Pro:mytestproject patrick$

For more information about npm and package management pls. check the getting started section on npm documentation site and the npm website .