Installing Packages with NPM
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 thenode_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.