Using NPM
In previous chapters we created a module for a web framework with some simple routing and parsing. Modules promote code reuse, and since so much of the logic of web applications is shared between every web application you write, there tends to be a lot of code reuse.
We also created some more specific modules in the last chapter - one for the guessing game logic and one for the database. While these are much more specific to our efforts, they are possibly reusable later as well.
Reusable code is made far more valuable when it is distributable. The ability to pull reusable modules into your code with ease is a tremendous "power up", because it allows you to make use of high quality components maintained by the wider community. One of the biggest strengths (although sometimes it's a weakness!) of Node.js is the ease of accessing and contributing to this ecosystem of reusable code modules.
Node Package Manager
The Node Package Manager - npm
- is our gateway into the wider development community in Node.js. npm
gives you access to hundreds of thousands of open source modules (packages) that you can use within your own program. We already saw two such modules: dotenv
and better-sqlite3
. At the time of this writing, the dotenv
modules is being downloaded over 42 million times per week, and there are over 50,000 known npm
modules that depend on it. better-sqlite3
is downloaded over 750 thousand times per week. There are many modules with sort of broad adoption.
Pro Tipđź’ˇ The ease in which you can install npm
packages, and the ease in which you can publish your own packages is a double-edged sword. Not every package on npm
is a good package - in fact, most are not! There is controversy within the developer community as to whether or not it's actually a good idea to be installing packages written by strangers. Common sense goes a long way here though. If you can write something yourself without a lot of effort, then don't install something from npm
- just write it yourself. If it's a lot of effort, or you know there are edge cases that would take a lot of skill to handle - and the job isn't a core part of the program you are creating - then take a look at npm
. Be cautious - if you find a package that has very little usage, be skeptical - and review the code. If you find a package that's downloaded and used by millions every week, have more confidence. Generally speaking, a heavily used npm
package has been vetted a lot more than an obscure one.
npm install
npm
is a command line tool installed on your machine when you install Node.js. The npm install command is used to download and install packages (modules) and their dependencies to a project. It enables developers to add new libraries or tools to their project, simplifying code management by avoiding the need to manually download and link external JavaScript libraries. The command can be used to install packages locally within a specific project or globally to make them accessible across your system.
Basic Usage
To install a package locally, run:
npm install package-name
This downloads the package and creates a node_modules
directory if it doesn’t already exist in the project root. The installed package will be added to the dependencies section of package.json
(if it’s set up), ensuring that it’s automatically installed when others set up the project. For instance:
npm install dotenv
This command installs the dotenv
locally and adds it as a dependency in package.json. If we are to take a look at the package.json
file of our last guessing game application, which also used better-sqlite3
, we'd see the following:
{
"dependencies": {
"better-sqlite3": "^11.5.0",
"dotenv": "^16.4.5"
}
}
Note the specific version listed. By default, when we use npm install
it will install the latest version of the module - however we can also install different versions. To install a specific version of a module with npm, you can specify the desired version number after the package name using the @ symbol. This is useful when you need to ensure compatibility with other parts of your project or avoid potential breaking changes in newer versions.
npm install package-name@version
For example, if for some reason we wanted an older version of better-sqlite3
, we could install it as follows:
npm install better-sqlite3@7.6.2
If you want flexibility but still want to avoid breaking changes, you can specify version ranges:
- Caret (^): Installs the latest minor/patch updates, but not major updates. For example, ^1.2.3 allows updates up to, but not including, 2.0.0.
npm install dotenv@^16.0.0
- Tilde (~): Installs the latest patch updates within the same minor version. For example, ~1.2.3 allows updates up to, but not including, 1.3.0.
npm install better-sqlite3@~7.6.0
Dependencies of Dependencies.
Modules that you install might depend on other modules. When you do an npm install
on a particular module, you also install that module's dependencies.
Let's take a look at better-sqlite3
. It actually uses two other packages - bindings
and prebuild-install
. These modules assist in compilation of the sqlite C language libraries, which needs to happen when installing better-sqlite3
. The beauty of npm
is that you do not need to know this - it automatically install all dependencies, recursively.
Installing all your dependencies
Perhaps the nicest thing about npm install
is that it always adds the package being installed to package.json
. Thus, package.json
becomes a complete listing of all your dependencies. Typically, when you distribute your program (or add it to git
), you leave out your dependencies (leave out node_modules
), and only include your package.json
file.
To install all dependencies listed in package.json for a project, simply use npm install without specifying a package name:
npm install
This command reads the package.json file, downloads all listed dependencies, and places them in node_modules. This is particularly useful for setting up a project from a version-controlled repository where the dependencies are listed in package.json but aren’t included directly.
Going forward, we will start adding lots of dependencies to our projects. We will start gaining a tremendous set of features this way. We will never distribute our application with the node_modules
directory however, just the package.json
file.
Where are all these modules coming from?
You might be wondering... how do you know which packages are out there? npm
works (by default) with the official Node.js package registry - www.npmjs.com. The site is fully searchable, and contains thousands and thousands of packages. One of the reasons it has so many is that it's actually really easy to publish to. In the next section, we'll see how easy it is - and publish some of our guessing game components to it.