Chapter 5 of 18 · Node.js for Beginners — Complete Free Tutorial
npm and package.json
Virtually every Node project begins with npm init. The Node.js for Beginners series now introduces npm: the registry, the command-line tool and the manifest file that together define your project. By the end you will read any package.json with confidence, install dependencies deliberately, and use scripts as your project's command menu.
Three things called npm
- The registry — a public database of published packages (express, lodash, jest…) with every version ever released.
- The CLI — the
npmcommand installed with Node that talks to that registry. - The configuration file —
package.json, the manifest every Node project carries.
A package is a folder with a manifest; it can contain a library, a CLI tool, or both. Installing one copies it into node_modules and records the intent in your manifest.
Anatomy of package.json
{
"name": "todo-api",
"version": "1.0.0",
"description": "A tiny to-do REST API",
"type": "module",
"main": "src/server.js",
"scripts": {
"start": "node src/server.js",
"dev": "node --watch src/server.js"
},
"keywords": ["todo", "api", "express"],
"license": "MIT",
"dependencies": {
"express": "^5.1.0"
},
"devDependencies": {
"nodemon": "^3.1.9"
}
}
| Field | Meaning |
|---|---|
name / version | Identity — required to publish; versions follow semantic versioning |
type | "module" makes .js files ESM; omit or set "commonjs" for require |
scripts | Commands run with npm run <name> — the project's menu |
dependencies | Needed in production |
devDependencies | Needed only while developing (test runners, linters, nodemon) |
Installing packages
npm init -y # create package.json with defaults
npm install express # add to "dependencies"
npm install --save-dev nodemon # add to "devDependencies"
npm install # install everything from the manifest
npm uninstall express # remove it and update the manifest
Expected output: each command prints a summary such as added 64 packages in 2s and rewrites package-lock.json. Modern npm saves to dependencies by default — --save is historical.
Version ranges explained
| Range | Meaning | Example versions allowed |
|---|---|---|
^5.1.0 | Minor and patch updates (default for installs) | 5.1.0 up to but not including 6.0.0 |
~5.1.0 | Patch updates only | 5.1.0 up to but not including 5.2.0 |
5.1.0 | Exact pin | 5.1.0 only |
* or latest | Whatever is newest — avoid in manifests | anything |
Semantic versioning reads major.minor.patch: breaking changes bump the major, features the minor, fixes the patch. ^ is safe for libraries because minors and patches are promised not to break you; exact pins belong in deployment-critical tools. When you are ready to publish your own package, the same manifest describes it for everyone else — npm publish uploads the folder, and consumers install exactly what your fields promise.
Scripts: your project's command menu
npm run dev
npm test
npm run lint
Expected output: the dev script above starts node --watch src/server.js, prints a watch message, and restarts the server every time you save a file — nodemon's job without the extra dependency (Node 18.11+ ships the flag).
npm startandnpm testare conventional names with built-in shorthand — norunneeded.- Anything else needs
npm run <name>. - Keep scripts portable: a shell script that only works on one OS will bite your teammates.
node_modules and the lock file
node_modules is a local cache of installed packages — delete it freely, npm install rebuilds it. package-lock.json is not deletable: it records the exact resolved version of every package in the tree, so every machine and CI run installs identical code. Commit the lock file; add node_modules to .gitignore. Three commands round out the daily routine: npm outdated shows what has drifted, npm audit reports known vulnerabilities in your tree, and npm ci does a clean, lock-file-exact install — the one CI pipelines should call instead of npm install.
Common mistakes
- Committing
node_modules— tens of thousands of files thatnpm installrecreates in seconds. - Deleting
package-lock.json— "it causes conflicts" is backwards; the lock file prevents environment drift. - Putting dev tools in
dependencies— bloats production installs; linters and test runners belong in dev. - Using
*ranges — a surprise major release becomes your surprise outage. - Running global installs for project tools — each project should declare its own versions so upgrades are deliberate.
Practice checklist
- Run
npm init -yin an empty folder and rewrite the generated fields to describe a real idea. - Install one runtime dependency and one dev dependency; confirm which array each landed in.
- Add a
startand adevscript and run both. - Read the lock file (just the first 30 lines) and find the resolved version of your dependency.
- Delete
node_modules, restore it withnpm install, and prove the app still runs.
Your toolchain is ready — now for the behaviour that defines Node itself. Next: Asynchronous JavaScript in Node.
Frequently Asked Questions
Node.js is a runtime that executes JavaScript outside the browser. It combines Google's V8 engine with APIs for files, networks, processes and streams, plus a package ecosystem (npm). You use it to build servers, command-line tools, APIs and anything that needs JavaScript running on a machine rather than in a page.
JavaScript is the language; Node.js is one environment that runs it. In the browser the language comes with a DOM, events and window APIs — in Node those are replaced by the file system, network and process modules. Syntax, functions, arrays, promises and async/await are identical, so your JavaScript knowledge transfers directly.
Browser code is sandboxed: it cannot read your files or open arbitrary ports. Node code has full machine access, which is why it is used for servers and tools but also why you never run untrusted code in it. There is no document or window in Node — the equivalents are global, process and modules.
npm is JavaScript's package manager and public registry. package.json describes your project: name, entry point, dependencies with version ranges, and scripts such as npm run dev. Installing a package copies it into node_modules and records the exact intent in package-lock.json so every machine installs identical versions.
Express is a minimal web framework for Node: a few thousand lines that give you routing, middleware, request parsing and static files on top of the raw HTTP server. It is the most common starting point for REST APIs and the backbone of this tutorial's project chapters.
Both work. CommonJS (require/module.exports) is the classic Node format; ES modules (import/export) are the standard and activated in a package.json with "type": "module". Modern projects favour ESM for browser compatibility, but you will read both in existing code, so this course teaches each.
Middleware are functions that run between the incoming request and the final response, in order: body parsing, logging, authentication, rate limits, error handling. Each receives the request, response and next function and can respond itself or pass control along — Express's pipeline model in one sentence.
A JSON file is perfect for learning CRUD: no setup, readable data, easy to reset. The moment you need concurrent writes, querying or multiple users, move to a real database — MySQL/PostgreSQL for relational data or MongoDB for documents. The storage chapter isolates persistence behind one module so swapping it later is straightforward.
A REST API exposes resources over HTTP using verbs on URLs: GET /api/todos lists, POST creates, PUT or PATCH updates, DELETE removes, and everything answers with JSON plus correct status codes (200, 201, 400, 404, 500). It is stateless — each request carries its own authentication — which makes it easy to cache, scale and consume from any frontend.
Node apps are long-running processes, not static files: deploy them to a Node-friendly host (a VPS, Render, Railway or Fly.io), keep secrets in environment variables, terminate HTTPS at a reverse proxy or platform edge, and send logs somewhere durable. The final chapter covers the full checklist including health checks and graceful shutdown.