npm (Node Package Manager) installs code other people have written and published, so you don't have to write everything yourself. It comes bundled with Node.js — you already have it.
Every Node project has a package.json file at its root — a plain JSON file describing the project: its name, version, dependencies, and the scripts you can run. Create one with:
npm init -yThe -y accepts all the defaults instead of asking questions one at a time. It produces something like:
{
"name": "my-app",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}npm install expressThis does three things: downloads the express package into a new node_modules folder, adds it to the "dependencies" list in package.json, and writes exact version numbers to package-lock.json.
package.json can list a dependency loosely, like "any version 4.x.x." package-lock.json records the exact version that was actually installed, for every package and everything those packages depend on. Committing this file means everyone on a team — and the server the app eventually runs on — installs the identical set of versions, instead of whatever happens to be newest on install day.
node_modules can easily reach hundreds of megabytes and is never committed to version control — anyone can rebuild it from package.json and package-lock.json with one command:
npm installRun with no package name, npm install reads package.json and installs everything listed. This is the command a teammate runs after cloning the project, and it's why the lock file is committed but the folder it fills isn't.
The "scripts" section in package.json gives shell commands short names:
{
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js"
}
}npm run devnpm start and npm test can drop the word "run" — those two are special-cased. Every other script needs it: npm run <name>.