Learn Node.js with real applications

Package Installation and Management

Installing and Managing Packages with npm

Along with the Node.js version, the package manager called npm is installed; it is a command-line utility that allows you to install, update, and publish packages for Node.js. By default, npm uses the public registry (https://www.npmjs.com) to perform all the operations mentioned above. However, if an organization requires it, they can create their own private registry so that their packages are not public and can be consumed privately.

For each Node.js installation, a default version of npm is installed. To check the installed version, run the following command:

npm -v

However, this does not mean that you cannot update the version of npm associated with the Node.js version selected with nvm. If necessary, you can update the version of npm with the following command:

npm install npm@latest --global

From then on, that version of npm will be updated for the Node.js version selected with nvm.

Installing Local Packages

npm allows you to install packages globally, such as npm itself or general binaries that will serve as command-line utilities. However, the most common use is to install them locally for a project. It is important to note that local packages are installed in the current directory of the terminal session. Therefore, it is always recommended to check the directory you are in within the terminal session before executing the installation command.

If you want to know more information about an installed package or do not know the specific name of a package, you can check the public npm registry (https://www.npmjs.com).

In the greeting project, install the colors package locally with the following command:

npm install colors

Note that within the current directory, a directory named node_modules has been created; this is used by npm to store all the packages installed in the project directory, and it is also used to resolve dependencies between different packages. If you check the contents of the directory, you will find the installed package there.

Next, install another package called chalk, but this time a specific version, version 4, which in turn depends on other packages. This will allow us to see where npm installs the package dependencies. In the same working directory, run the following command:

npm install chalk@4

You can view the contents of the node_modules directory from the terminal with the following command:

ls node_modules

If you check the contents of node_modules again, you will notice that the dependencies of the chalk package have also been installed, and all dependencies are at the same level. This type of organization used by npm is called flat installation.

To uninstall a package, use the following command:

npm uninstall chalk

With the installation (or uninstallation), npm analyzes the packages and their dependencies, creating a dependency tree. This is very useful for maintaining the integrity of the project. Therefore, if a package being uninstalled had a common dependency with another package, the previous command does not delete that dependency.

For more information about npm, you can refer to the official usage guide.

Managing Package Versions

You may notice that a file named package-lock.json has been created, which stores the exact version of each library that is installed along with all its dependencies. npm ensures that each library with common dependencies meets all requirements by resolving any conflicts that may exist between different versions. Once this work is done, it is recorded in the file. This offers a significant advantage when another user reinstalls all the project dependencies, as dependency resolution will be performed deterministically, ensuring the installation of the same version of the libraries and their dependencies. This cannot be guaranteed without this file, because when reinstalling the project’s libraries and dependencies, new or even deprecated versions may exist.

The package-lock.json file has been available since version 5 of npm.

Using Local Packages

To use the recently installed library, edit the index.js file as follows:

const colors = require('colors/safe');

const args = process.argv.slice(2);
const [name = 'Friend'] = args;
const hour = new Date().getHours();

// Ask for hours range
if (hour >= 6 && hour < 12) {
  console.log(colors.yellow(`Good morning ${name}`));
} else if (hour >= 12 && hour < 18) {
  console.log(colors.green(`Good afternoon ${name}`));
} else if (hour >= 18 && hour < 23) {
  console.log(colors.cyan(`Good evening ${name}`));
} else {
  console.log(colors.blue(`Good night ${name}`));
}

Run the application in the terminal with the following command:

node index.js Gustavo

The file extension is optional, so the following command is equivalent: node index.

You will see in the console that the message is displayed in the specified color. This is achieved because the application used the colors package, which was automatically found in the local node_modules directory.

For more information about the colors library, you can visit its official webpage.

Installing and Using Global Packages

As mentioned earlier, global packages, as the name suggests, are not installed in any local directory; they are installed globally for the Node.js version selected with nvm. This means that when switching Node.js versions with nvm, only the global packages installed for the selected version will be available.

Being global, they can be used in any project or executed from any directory selected from the terminal. This may sound like a huge advantage, but it is NOT a recommended practice. Each project should declare in its manifest (which will be detailed in the next section) all the packages it needs to run, both in development and production. This section is for informational purposes.

As an example, proceed to install the ESLint package, which helps check the syntax of JavaScript files. To install it globally, add the -g or --global flag:

npm install --global eslint

Note that npm creates an executable file shortcut for the package to be accessed from the terminal.

In the working directory, create a temporary file named temp.js to intentionally add an error to demonstrate the utility of the ESLint package, with the following content:

var ups = ;

Run ESLint to check the syntax of our temporary application:

eslint --no-eslintrc temp.js

Many global packages are even used to create many local workflow scripts in the system.

You get the following output:

1:11 error Parsing error: Unexpected token ;


1 problem (1 error, 0 warnings)

For ESLint, you can define all the syntax rules and even extend from an existing style guide. For more information, you can visit the ESLint Getting Started Guide.

Package Resolution

An important question is what would happen if you have a package installed both locally and globally. Which version would Node.js use? In this case, Node.js first looks for the package in the project’s local directory (node_modules); if it doesn’t find it, it proceeds to look for the package in the global installation, and finally, if it doesn’t find it, it shows an error.

Other Package Managers

The fact that npm is automatically installed with Node.js does not mean it is the only package manager. Yarn was released to the public in 2016 as one of Facebook’s open-source projects. It has been well-received, with its main feature being the speed of package installation due to a deterministic approach.

Yarn uses the same manifest file as npm (package.json), as well as the directory where packages are installed (node_modules), so it can be used without significant changes as a package manager in a Node.js project. If it is an existing project, it is recommended to delete the node_modules directory and perform a “clean” installation. It is not recommended to use both npm and Yarn simultaneously in the same project.

If you have Homebrew installed on Mac OS, you can install Yarn with the following command:

brew install yarn

It can even be installed with npm using the following command:

npm install -g yarn

To learn more about the usage options of Yarn, you can visit the Yarn Usage Guide.