npm and package.json

Node.js · Essentials · 12 min

Almost every Node project starts with package.json and depends on packages from the npm registry.

npm ships with Node and does two jobs: it installs packages from the public registry, and it runs your project's scripts. A project is any folder with a package.json, created with npm init -y.

The fields you will touch most:

  • name, version — identity, required if you publish.
  • type — set to "module" for ES modules.
  • scripts — named commands: "dev": "node --watch src/server.js", "test": "node --test". Run them with npm run dev; npm test and npm start are shortcuts.
  • dependencies — packages your code needs at runtime.
  • devDependencies — tools only needed while developing (test helpers, linters, TypeScript).
  • engines — the Node versions you support, e.g. ">=22".

Installing:

npm install express          # adds to dependencies
npm install -D eslint        # adds to devDependencies
npm uninstall express
npx eslint .                 # run a package's binary without a global install

Packages land in node_modules/, a folder you never edit and never commit (add it to .gitignore). Node finds packages there by walking up from the importing file's directory.

Scripts run with node_modules/.bin on the PATH, so "lint": "eslint ." uses the locally installed eslint — no global installs needed, and every developer gets the same version.

Avoid npm install -g for project tools; keep them in devDependencies so the project describes everything it needs. Global installs are fine for personal utilities you use across projects.

Example

# Start a project and add a dependency
mkdir hello-api && cd hello-api
npm init -y
npm pkg set type=module
npm pkg set scripts.dev="node --watch server.js" scripts.test="node --test"
npm install express
npm install -D @types/node

# package.json now contains (abridged):
# {
#   "name": "hello-api",
#   "type": "module",
#   "scripts": { "dev": "node --watch server.js", "test": "node --test" },
#   "dependencies": { "express": "^5.1.0" },
#   "devDependencies": { "@types/node": "^22.10.0" }
# }

npm run dev        # or: node --run dev
npx eslint --version

Remember

  • package.json describes the project: type, scripts, dependencies
  • dependencies for runtime, devDependencies for tooling
  • Never edit or commit node_modules; npx runs local binaries

Watch out for

  • Installing project tools globally so the project silently depends on your machine.

Check yourself

  1. A test framework your code only uses during development should be installed with…

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nodejs.org/learn/getting-started/an-introduction-to-the-npm-package-manager