Installing Packages with NPM

Learn about packages and configuring files that Git should ignore.

Box Cat

As we previously learned, Express is a framework for Node that will handle our web server.

Thus far, we have initialized NPM but haven't installed any packages. So the first order of business is to install Express via NPM. However, installing packages results in a directory that Git should not track, so let's also look at ignoring things in Git. In addition, you'll learn there are different types of packages and dependencies.

The commands you need to know here on a day-to-day basis are pretty simple. However, understanding the options and what's going on is more complex. As a result, most of this article goes into detail to prevent future confusion.

Install Express

First, open VS Code, then open the integrated Terminal.

View > Terminal or Control + ` (grave accent)

In the Terminal, type npm i -S express or npm install --save express.

You can learn more about the package you're installing on the NPM website.

https://www.npmjs.com/package/express

Express is a "Fast, unopinionated, minimalist web framework for node."

If you don't install Express, down the road, you'll see:

Error: Cannot find module 'express'

After installing, you should see a change to the package.json file.

  "dependencies": {
    "express": "^4.17.1"
  }

Let's also install a tool called nodemon that will save time in development. "nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected."

https://www.npmjs.com/package/nodemon

npm i -D nodemon or npm install --save-dev nodemon

  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.12"
  }

After installing Express in your project directory, you should see the following folder and file.

node_modules

package-lock.json

Node modules

"Package is a term used by npm to denote tools that developers can use for their projects... The packages will come in a folder typically called node_modules, which will also contain a package.json file. This file contains information regarding all the packages including any dependencies, which are additional modules needed to use a particular package."

https://devtut.github.io/nodejs/npm.html#installing-packages

Package lock

"package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates."

https://docs.npmjs.com/cli/v7/configuring-npm/package-lock-json

Global or local packages

We could have installed nodemon as a global package like this.

npm install -g nodemon

"The main difference between local and global packages is this:

  • local packages are installed in the directory where you run npm install <package-name>, and they are put in the node_modules folder under this directory
  • global packages are all put in a single place in your system (exactly where depends on your setup), regardless of where you run npm install -g <package-name>"

https://nodejs.dev/learn/npm-global-or-local-packages

"In general, the rule of thumb is:

  • If you’re installing something that you want to use in your program, using require('whatever'), then install it locally, at the root of your project.
  • If you’re installing something that you want to use in your shell, on the command line or something, install it globally, so that its binaries end up in your PATH environment variable."

https://nodejs.org/en/blog/npm/npm-1-0-global-vs-local-installation/

The problem with npm install --global. "It's certainly quick and easy to start using a new tool that's globally installed, which is why a lot of "getting started" guides recommend it. Also, the problems you'll experience might take you weeks or months to notice."

https://ericlathrop.com/2017/05/the-problem-with-npm-install-global/

"If your project depends on a package, it should be listed in your package.json file as a dependency and installed locally in your project, rather than globally."

https://www.smashingmagazine.com/2016/01/issue-with-global-node-npm-packages/

"What are the pros and cons of installing all npm modules globally?"

https://www.quora.com/What-are-the-pros-and-cons-of-installing-all-npm-modules-globally

"With a local installation, nodemon will not be available in your system path or you can't use it directly from the command line."

https://github.com/remy/nodemon#installation

For the sake of example, let's leave nodemon as a local install. We'll tackle this problem in the following article.

Dependencies

Look in package.json again and notice dependencies and devDependencies.

"When you install an npm package using npm install <package-name>, you are installing it as a dependency.

The package is automatically listed in the package.json file, under the dependencies list (as of npm 5: before you had to manually specify --save).

When you add the -D flag, or --save-dev, you are installing it as a development dependency, which adds it to the devDependencies list.

Development dependencies are intended as development-only packages, that are unneeded in production."

https://nodejs.dev/learn/npm-dependencies-and-devdependencies

For example, when we deploy our back-end code to a server, our application will be running all the time; we won't need to apply new changes or automatically restart the server with nodemon. There are exceptions shown in the FAQ.

https://github.com/remy/nodemon/blob/master/faq.md#using-nodemon-with-forever

It's ok to install some packages globally. For example, scaffolding tools you use once for a setup like create-react-app and utility tools like nodemon are ok because they don't know anything about your project.

https://ericlathrop.com/2017/05/the-problem-with-npm-install-global/

Configuring NPM

Guidance on configuring package.json is available on NPM.

https://docs.npmjs.com/cli/v7/configuring-npm/package-json

Uninstall a package

"To remove a package from your node_modules directory, on the command line, use the uninstall command. Include the scope if the package is scoped."

https://docs.npmjs.com/uninstalling-packages-and-dependencies

npm uninstall <package_name>

"To remove a package from the dependencies in package.json, use the --save flag. Include the scope if the package is scoped."

npm uninstall --save <package_name>

You can also delete dependencies from your package.json file, save, and run npm i again.

Git ignore

"A gitignore file specifies intentionally untracked files that Git should ignore."

http://git-scm.com/docs/gitignore

It's a best practice not to track changes to irrelevant files. You don't want to push unnecessary garbage to a shared repository on GitHub. Also, not tracking specific files like a .env file is crucial for maintaining security when publishing your work to GitHub.

"You can create a .gitignore file in your repository's root directory to tell Git which files and directories to ignore when you make a commit."

https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files

touch .gitignore (Note that this is a hidden file, so it begins with a period.)

There are many .gitignore resources and generators. Unfortunately, many of these preconfigured lists make many assumptions about what tools you'll be using, your operating system, testing settings, server environment for deployment, and continuous delivery. The result is a lot of unnecessary noise. In addition, most of these long lists don't explain anything about why you need to exclude tracking. Finally, keep in mind that an open-source project will likely have contributors who use different operating systems.

https://www.toptal.com/developers/gitignore/api/macos,node

https://github.com/github/gitignore/blob/master/Node.gitignore

For now, let's start by adding the following to our .gitignore file and saving it.

# macOS
.DS_Store

# Dependency directories
node_modules/

".DS_Store is a hidden file that gets generated whenever someone opens a directory in the finder."

https://chaseadams.io/posts/my-gitignore-conventions/

"Ignored files are usually build artifacts and machine generated files that can be derived from your repository source or should otherwise not be committed. Some common examples are: dependency caches, such as the contents of /node_modules or /packages"

https://www.atlassian.com/git/tutorials/saving-changes/gitignore

In other words, developers use a list of NPM package dependencies in package.json to install the project locally. After downloading or cloning any project, the first step is to run install (i.e., npm install or npm i).

When deploying our back-end code to a server, we invoke npm i to install packages on that remote computer. Developer dependencies are extraneous.

Summary

In this article, the main lessons are using npm i <package_name> to install third-party packages and creating a .gitignore file to exclude the node_modules folder from Git.

We'll continue working with NPM and Express in the following article.

https://www.gamesoflight.com/start-an-express-server/