Categories
JavaScript Nodejs

How To Run Multiple Versions of Node.js on Linux

If you are managing multiple Node.js projects, they might be running different versions of Node.js.

Node.js does not support running different versions of the runtime concurrently. This means you have to use third-party software to do it.

To do this on Linux, all you have to do is install some extra packages and then you can install different versions of Node.js on your computer. One of the easiest ways to get different versions of Node.js on your computer is to use [nvm](https://github.com/nvm-sh/nvm).

nvm is available for free for anyone to download. To download it, download with curl and install it:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

Or, alternatively, you can do the same thing with wget:

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

What the script does is clone the nvm repository to ~/.nvm and add the source line to your profile (~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc).

To load nvm, put the following in your profile file (~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc):

export NVM_DIR="${XDG_CONFIG_HOME/:-$HOME/.}nvm"  
[ -s "$NV_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm

The --no-use option is available if you add the --no-use after nvm.sh, so that it won’t pick the default version of Node.js.

You can check the nvm version by running nvm -v.

Alternatively, you can clone the Git repository for nvm manually and install it. You can do this by running:

$ cd ~/  
$ git clone https://github.com/nvm-sh/nvm.git .nvm

Then, add the following to your ~/.bashrc, ~/.profile, or ~/.zshrc file to have it run on login:

export NVM_DIR="$HOME/.nvm"  
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm  
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

nvm is ready to use once you install at least one version of Node.js.

To install the latest one, run nvm install node, or to install an earlier version, run nvm install 6.14.4. The first version of Node.js installed will be the default version.

To list the versions of Node.js installed, run:

nvm ls-remote

When you open a new shell, you have to run nvm again.

You can also run the node command with nvm run.

For example, nvm run node -v. To choose the version you want to run, run nvm exec 4.2 node — v.

To install the path of one version of Node.js runtime, run:

nvm which 10.16

You can install the latest long term support (LTS) version without specifying the version. To do this, run nvm install --lts.

To install other LTS versions of Node.js, you can specify those by their codename, for example, nvm install — lts=carbon.

Other example commands include:

  • nvm install lts/carbon: Installs the latest 8.x version of Node.js.
  • nvm uninstall --lts: Remove the latest LTS version.
  • nvm uninstall --lts=carbon: Remove the latest 8.x version of Node.js.
  • nvm uninstall 'lts/*': Uninstall all LTS versions of Node.js.
  • nvm uninstall lts/carbon: Uninstall the latest 8.x version of Node.js.
  • nvm use --lts: Use the latest LTS version of Node.js.
  • nvm use --lts=carbon: Use the latest 8.x version of Node.js.
  • nvm use 'lts/*': Use the latest LTS version of Node.js installed.
  • nvm use lts/carbon: Use the 8.x version of Node.js.
  • nvm exec --lts: Run a Node.js script with the latest LTS version of Node.js.
  • nvm exec --lts=carbon: Run the Node.js script with the latest 8.x version of Node.js.
  • nvm exec 'lts/*': Run a Node.js script with the latest LTS version of Node.js.
  • nvm exec lts/carbon: Run a Node.js script with the latest 8.x version of Node.js.
  • nvm run --lts: Run a Node.js script with the latest LTS version of Node.js.
  • nvm run --lts=carbon: Run a Node.js script with the latest 8.x version of Node.js.
  • nvm run 'lts/*': Run a Node.js script with the latest LTS version of Node.js.
  • nvm run lts/carbon: Run a Node.js script with the latest 8.x version of Node.js.
  • nvm ls-remote --lts: List all the LTS versions of Node.js.
  • nvm ls-remote --lts=carbon: List all 8.x versions of Node.js.
  • nvm ls-remote 'lts/*': List all the LTS versions of Node.js.
  • nvm ls-remote lts/carbon: List all 8.x versions of Node.js.
  • nvm version-remote --lts: List the latest LTS version of Node.js.
  • nvm version-remote --lts=carbon: List the latest 8.x version of Node.js.
  • nvm version-remote 'lts/*': List the latest LTS version of Node.js.
  • nvm version-remote lts/carbon: List the latest 8.x version of Node.js.

To migration global packages while installing nvm, run:

nvm install node --reinstall-packages-from=node

It will identify the version of Node you are migration from, by running nvm version node before migrating. Then, it will run nvm reinstall-packages to reinstall the packages into your new environment.

You can also specify the versions of Node.js migrate to and from:

nvm install 8--reinstall-packages-from=5  
nvm install 8--reinstall-packages-from=argon

To use the system version of Node.js, run:

nvm use system

To list the versions of Node.js installed, run:

nvm ls

And, to see the available versions you can install, run:

nvm ls-remote

By default, nvm ls, nvm ls-remote, and nvm alias output in color text. You can disable color text output by running:

nvm ls --no-colors

Run nvm deactivate to deactivate nvm and restore your original PATH environment variable.

Finally, to set the default Node.js version for a new shell, run:

nvm alias default node

nvm is one of the easiest programs to manage multiple Node.js versions on your Linux computer. It also works with Windows Subsystem for Linux.

Categories
JavaScript Nodejs React

How to Solve the ‘create-react-app command not found’ Error

The ‘create-react-app command not found’ error occurs because we’re trying to run it locally when it’s not installed.

To fix that, we should run npm i -g create-react-app project-name to install it globally on our computer and run it.

Alternatively, we can also run npx create-react-app project-name to run it without install it.

In both cases, we need Node.js with NPM installed to run create-react-app.

If not, then we’ve to install it.

Categories
JavaScript Nodejs

How to Use NPM to Manage JavaScript Dependencies

NPM is the most popular package manager for Node.js. It is often used for installing and uninstalling packages. but can also be used for running custom scripts and performing other operations to packages.

The most common operations for developers are installation, clean up, removing duplicates, and running scripts.

npm install

npm install , or npm i for short, is used to install packages. If you don’t put a package name after install, it downloads all the packages listed in package.json if the dependencies aren’t installed yet or the version installed is outdated. If you put a package name after npm install, it will install the package with that name as long as it finds the package. During the installation process, npm will run npm run link and npm run build to compile the packages. You can install packages globally by running npm install -g packageName

npm audit

npm audit is used for running a security audit of the npm packages you installed. It will display the results of the audit in various formats. You can also fix any security vulnerabilities with npm audit fix. To do a dry run, you can do npm audit fix --dry-run .

Both the audit and fix can be displayed in JSON by including --json to the command, such as npm audit --json and npm audit fix --json.

Example output:

=== npm audit security report ===
# Run  npm update set-value --depth 12  to resolve 66 vulnerabilities
High            Prototype Pollution
Package         set-value
Dependency of   @angular-devkit/build-angular [dev]
Path            @angular-devkit/build-angular > sass > chokidar > anymatch >
                  micromatch > braces > snapdragon > base > cache-base >
                  set-value
More info       https://npmjs.com/advisories/1012
High            Prototype Pollution
Package         set-value
Dependency of   @angular-devkit/build-angular [dev]
Path            @angular-devkit/build-angular > webpack > watchpack >
                  chokidar > anymatch > micromatch > braces > snapdragon >
                  base > cache-base > set-value
More info       https://npmjs.com/advisories/1012
High            Prototype Pollution
Package         set-value
Dependency of   @angular-devkit/build-angular [dev]
Path            @angular-devkit/build-angular > webpack-dev-server >
                  chokidar > anymatch > micromatch > braces > snapdragon >
                  base > cache-base > set-value
More info       https://npmjs.com/advisories/1012
High            Prototype Pollution
Package         set-value
Dependency of   @angular/compiler-cli [dev]
Path            @angular/compiler-cli > chokidar > anymatch > micromatch >
                  braces > snapdragon > base > cache-base > set-value
More info       https://npmjs.com/advisories/1012
...

npm bin

npm bin prints the folder where packages are installed.

Example output:

c:\math-calculator>npm bin  
c:\math-calculator\node\_modules\.bin

npm ci

npm ci is used to install all packages from scratch from package-lock.json. If there are any discrepancies between package.json and package-lock.json, it will fail. node_modules will be deleted and everything will be installed from scratch.

You can tab completion to npm by including npm completion in your ~/.bashrc or ~/.zshrc.

npm-config

npm-config is used for saving configuration key-value pairs to npmrc . To set a key-value pair in npmrc, we put:

npm config set key value

To get a value from the key, we run:

npm config get key

We can list all values by running:

npm config list

We can delete the key-value pair by running:

npm config delete key

and we can edit the key-value pair by running:

npm config edit

You can append — global to the above commands to change global config.

npm dedupe

npm dedupe will remove duplicate dependencies from your node_modules folder by moving the dependencies up the dependency tree, allowing common dependencies for multiple packages to reference one dependency.

npm doctor

npm doctor runs checks to make sure your environment has everything to manage Git packages. It checks if Node.js and Git can be run. It also checks if the primary npm registry or an alternative is accessible. node_modules is checked if it can be accessed and is writable, and it checks if the npm cache exists and there are no corrupt packages:

Example output of npm doctor:

npm notice PING https://registry.npmjs.org/
npm WARN verifyCachedFiles Content garbage-collected: 1328 (139761056 bytes)
npm WARN verifyCachedFiles Missing content: 5
npm WARN verifyCachedFiles Cache issues have been fixed
Check                               Value                             Recommendation
npm ping                            OK
npm -v                              v6.9.0                            Use npm v6.10.3
node -v                             v10.16.0                          Use node v10.16.2
npm config get registry             https://registry.npmjs.org/
which git                           C:\Program Files\Git\cmd\git.EXE
Perms check on cached files         ok
Perms check on global node_modules  ok
Perms check on local node_modules   ok
Verify cache contents               verified 8899 tarballs

npm explore

npm explore is used when you need to browse for an installed package. Once you’re in the package directory, you can run commands there.

npm help

npm help-search and npm help commands are used to find help with npm commands.

npm init

npm init is used for adding package.json to a project if it doesn’t already exist. npm init -y is used for skipping all the questions asked before creating the file.

npm outdated

npm outdated is used for checking for outdated packages.

Example output:

Package                            Current   Wanted   Latest  Location
@angular-devkit/build-angular      0.800.3  0.800.6  0.802.1  math-calculator
@angular/animations                  8.0.2    8.2.1    8.2.1  math-calculator
@angular/cdk                         8.0.1    8.1.2    8.1.2  math-calculator
@angular/cli                         8.0.3    8.0.6    8.2.1  math-calculator
@angular/common                      8.0.2    8.0.3    8.2.1  math-calculator
@angular/compiler                    8.0.2    8.0.3    8.2.1  math-calculator
@angular/compiler-cli                8.0.2    8.0.3    8.2.1  math-calculator
@angular/core                        8.0.2    8.0.3    8.2.1  math-calculator
@angular/forms                       8.0.2    8.0.3    8.2.1  math-calculator
@angular/language-service            8.0.2    8.0.3    8.2.1  math-calculator
@angular/material                    8.0.1    8.1.2    8.1.2  math-calculator
@angular/platform-browser            8.0.2    8.0.3    8.2.1  math-calculator
@angular/platform-browser-dynamic    8.0.2    8.0.3    8.2.1  math-calculator
@angular/router                      8.0.2    8.0.3    8.2.1  math-calculator
@ngrx/store                          8.0.1    8.2.0    8.2.0  math-calculator
@types/jasmine                      3.3.13   3.3.16    3.4.0  math-calculator
@types/node                          8.9.5    8.9.5   12.7.1  math-calculator
karma                                4.1.0    4.1.0    4.2.0  math-calculator
karma-chrome-launcher                2.2.0    2.2.0    3.0.0  math-calculator
karma-coverage-istanbul-reporter     2.0.5    2.0.6    2.1.0  math-calculator
mathjs                               6.0.2    6.0.4    6.0.4  math-calculator
rxjs                                 6.4.0    6.4.0    6.5.2  math-calculator
ts-node                              7.0.1    7.0.1    8.3.0  math-calculator
tslint                              5.15.0   5.15.0   5.18.0  math-calculator
typescript                           3.4.5    3.4.5    3.5.3  math-calculator
zone.js                              0.9.1    0.9.1   0.10.1  math-calculator

npm ls

npm ls lists installed packages in the current project. npm list and npm la are aliases of this command.

npm prune

npm prune removes unused packages. npm run --production is used to delete packages from the devDependencies section. The --dry-run option is used for checking which packages will be deleted before the actual run. The --json option can be used to display results in JSON. With package-lock enabled, pruning is automatic.

npm root

npm root displays the root folder for Node packages in the project.

npm run

npm run-script lets you run custom scripts that you write. npm run is an alias of this command.

npm start

npm start starts a package by running the command you define.

npm search

npm search is used to search for packages by name.

npm shrinkwrap

npm shrinkwrap creates npm-shrinkwrap.json by repurposing package-lock.json or creating from scratch. npm-shrinkwrap.json takes precedence over package-lock.json .

npm stop

npm stop stops a package by running stop command that you define.

npm test

npm test allows you to run tests with a script that you define.

npm uninstall

npm uninstall is used for uninstalling packages. You can add -g at the end to remove global packages.

npm update

npm updateupdates packages in the project. npm update packageName updates only the package with the name packageName . It will record the latest version to package-lock.json .

To upgrade npm to the latest version, run npm install -g npm.

Categories
JavaScript Nodejs

Add Logging to a Koa App with koa-logger

Koa doesn’t come with any logger built-in. Therefore, to see what’s happening with our app, we’ve to log them with a 3rd party logger.

One logger that’s compatible with the Koa framework is the koa-logger package.

Getting Started

To install it, we just run:

npm install koa-logger

and then we can use it by writing:

const logger = require('koa-logger')
const Koa = require('koa')

const app = new Koa()
app.use(logger())

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

All we did is to call use with the return value of the logger middleware passed in, then we get logging automatically.

Now when we start our app, we some output logged.

If we run the code above, we get the following output:

Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
Hint: hit control+c anytime to enter REPL.
Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,
  keepAliveTimeout: 5000,
  maxHeadersCount: null,
  headersTimeout: 40000,
  _connectionKey: '6::::3000',
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(kCapture)]: false,
  [Symbol(asyncId)]: 6
}
  <-- GET / [
Hint: hit control+c anytime to enter REPL.
Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,
  keepAliveTimeout: 5000,
  maxHeadersCount: null,
  headersTimeout: 40000,
  _connectionKey: '6::::3000',
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(kCapture)]: false,
  [Symbol(asyncId)]: 6
}
  <-- GET /
  --> GET / 200 8ms 11b

Custom Logging

The logger middleware function can take an optional callback as an argument.

The callback has the str parameter with the logging output as a string.

args has extra information about the request that’s made, including response time and the size of the response.

We can customize the logging by writing:

const logger = require('koa-logger')
const Koa = require('koa')

const app = new Koa()
app.use(logger((str, args) => {
  console.log(str, args);
}))

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

We have the callback:

(str, args) => {
  console.log(str, args);
}

Instead of nothing that we have in the previous example.

The result of this change is the following output:

Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,
  keepAliveTimeout: 5000,
  maxHeadersCount: null,
  headersTimeout: 40000,
  _connectionKey: '6::::3000',
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(kCapture)]: false,
  [Symbol(asyncId)]: 6
}
  <-- GET / [
  '  \u001b[90m<--\u001b[39m \u001b[1m%s\u001b[22m \u001b[90m%s\u001b[39m',
  'GET',
  '/'
]
  --> GET / 200 13ms 11b [
  '  \u001b[90m-->\u001b[39m \u001b[1m%s\u001b[22m \u001b[90m%s\u001b[39m \u001b[32m%s\u001b[39m \u001b[90m%s\u001b[39m \u001b[90m%s\u001b[39m',
  'GET',
  '/',
  200,
  '13ms',
  '11b'
]

We get extra information from the args object.

Alternatively, we can pass in an object with the transporter property to logger:

app.use(logger({
  transporter: (str, args) => {
    // ...
  }
}))

We can add logging to a Koa app with the koa-logger package, which is very simple to use.

With this, we don’t have to create our own logging solution.

Categories
JavaScript Nodejs

Using dotenv Node Package to Read Environment Variables

We can use the dotenv Node package to read environment variables into our Node app.

To install it, we run:

npm i dotenv

Then in our .env file, we add:

DB_HOST=localhost
DB_USER=root
DB_PASS=password

In index.js, we write:

require('dotenv').config();
console.log(process.env);

Then we get something like the following from the console log output"

{
  NODE_VERSION: '12.16.2',
  HOSTNAME: 'f99aa86838ab',
  YARN_VERSION: '1.22.4',
  HOME: '/home/runner',
  PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
  NODE_PATH: '/usr/local/lib/node_modules:/home/runner/node_modules',
  PWD: '/home/runner',
  TERM: 'xterm-256color',
  DB_HOST: 'localhost',
  DB_USER: 'root',
  DB_PASS: 's1mpl3'
}

As we can see, we have the environment variable values stored in the process.env object.

Now we can use them in whatever way we wish to.

We can also change where the environment variables are read from and the encoding of the text of the .env file.

For instance, we can change the path of the file as follows:

require('dotenv').config({ path: './env.test' });

Now dotenv will read from .env.test.

We can also change the encoding to read the text file with by writing:

require('dotenv').config({ encoding: 'latin1' });

This is the most popular package for reading environment variables and since it’s this easy to use, we know why it’s the case.