1.4npm: package.json, dependencies, scripts, versions
The essentials in 30 seconds
- package.json = the manifest: name, version, dependencies, scripts — created with npm init, the reference point of every project.
- The recipe, not the result: version package.json + package-lock.json (exact versions), never node_modules (regenerable via npm install).
- Semver + scripts + audit: MAJOR.MINOR.PATCH (^ and ~), standard commands via npm run, vulnerabilities via npm audit.
Running mini-case — Salim sets up his project in Algiers
Salim receives the startup's project: a folder with code but no package.json, and a colleague sends him node_modules as an attachment. He restarts cleanly: npm init to create the manifest, installing packages (dependencies vs devDependencies), start/dev/test scripts, .gitignore excluding node_modules, and a first npm audit revealing a vulnerable dependency to update. The project becomes installable with one command: npm install.
Last episode of case 1.1-1.3 — Salim equips his project after the language, asynchrony and modules.
1. package.json & dependencies: the manifest
npm gives access to the world's largest open-source registry: you install packages instead of coding everything. The heart of the project is package.json (name, version, dependencies, scripts), created with npm init. npm install express downloads into node_modules and adds to dependencies. Distinguish dependencies (production) from devDependencies (dev only, -D). package-lock.json locks exact versions (reproducibility); node_modules is not versioned (regenerable).
Salim runs npm init -y, installs the framework as a dependency and the restart tool as a devDependency: the project now installs with one npm install on any machine.
2. Semver, scripts & security
Semantic versioning (semver) follows MAJOR.MINOR.PATCH: major = breaking changes, minor = compatible new features, patch = bugs. ^4.18.2 allows minor/patch updates, ~4.18.2 patch only. Scripts (start, dev, test) run with npm run <nom> and standardise commands. And npm audit reports dependency vulnerabilities — to watch, since dependency flaws are a real risk.
Salim defines start, dev and test in his scripts and makes npm audit his reflex before each production release.
3. Choose packages without exposing yourself
The huge ecosystem is a strength (don't reinvent the wheel) and a risk (flaws, varying quality, abandoned packages). To choose: popularity (downloads, adoption), active maintenance (recent updates, handled issues), serious documentation, minimal scope (no big package for a trivial function). And for Git: version package.json + lock, never node_modules nor secrets (.env).
Salim checks downloads and the latest update before installing, and adds node_modules/ and .env to .gitignore from the first commit.
🔎 Concrete example — 🔎 Concrete example — Initialise and install
The basic commands, in order.
npm init -y # creates package.json
npm install express # dependency (production)
npm install -D nodemon # devDependency (dev)
npm run dev # runs the "dev" script
npm audit # known vulnerabilities
Reading: -D marks dev tools; npm run launches the manifest's scripts.
Lesson: ignore node_modules and .env in .gitignore — a reflex from the first commit.
Section vocabulary
- npm & the registry
- Node's package manager, giving access to the world's largest open-source registry (hundreds of thousands of reusable libraries).
Simple example: The web framework installed by Salim instead of being recoded.
What it is not: recoding an HTTP router or database client yourself.
Reflex: look for the proven package before recoding.
- package.json
- The project manifest: name, version, dependencies, scripts, metadata. Created with npm init; the reference point of every Node project.
Simple example: Salim's package.json with start, dev and test.
What it is not: a code folder with no manifest, not cleanly installable.
Reflex: npm init from day one of the project.
- dependencies vs devDependencies
- dependencies: needed in production. devDependencies: useful in dev only (installed with -D). node_modules: folder of installed packages, not versioned, regenerable.
Simple example: The framework in dependencies, the restart tool in devDependencies in Salim's project.
What it is not: sending node_modules as an attachment to a colleague.
Reflex: -D for tools, Git ignores node_modules.
- package-lock.json
- File locking the EXACT installed versions; guarantees everyone installs rigorously the same versions (reproducibility).
Simple example: The lock making Salim's machine and production install the same thing.
What it is not: “it works on my machine” with different versions everywhere.
Reflex: version the lock, never edit it by hand.
- semver & npm scripts
- MAJOR.MINOR.PATCH versioning (^ allows minor/patch, ~ patch only). Scripts define reusable commands (npm run
). Simple example: The ^ letting security patches through for Salim, and his npm run dev.
What it is not: versions frozen forever or different commands per developer.
Reflex: understand ^ / ~, standardise via scripts.
In practice — Hands-on — Manage a project with npm
- Initialise a project with npm init -y and examine the generated package.json (name, version, scripts).
- Install a package (npm install express) and a devDependency (npm install -D nodemon); observe node_modules, package.json and package-lock.json.
- Add scripts to package.json ("start", "dev") and run them with npm start / npm run dev.
- Understand semver (^ vs ~), ignore node_modules (.gitignore), and run npm audit to spot vulnerabilities.
Ready-to-say script — set npm hygiene as a team (30 s)
“We version package.json and the lock, never node_modules — everyone regenerates with npm install. Dev tools go in -D, commands in scripts, and we run npm audit before each release.”
To say when starting the project; check .gitignore at the first commit.
Copy-paste template — minimal package.json + .gitignore
{
"name": "projet-salim",
"version": "1.0.0",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"test": "jest"
},
"dependencies": {},
"devDependencies": {}
}
// .gitignore:
// node_modules/
// .env
Project with no manifest
Like Salim: npm init -y, reinstall packages one by one distinguishing prod and -D, recreate scripts — never take someone else's node_modules.
Team in Algiers
Same start/dev/test scripts for everyone: each developer runs the same commands, no more “I used to do it differently”.
Careful version bump
Read what ^ and ~ allow before updating; test after each minor bump, lock via the lockfile.
Imminent release
npm audit before releasing: fix reported vulnerabilities, check that .env and node_modules are properly out of Git.
✓ Best practices
- Version json + lock, never node_modules.
- Dev tools in -D, commands in scripts.
- npm audit before each release.
✗ Common pitfalls
- Versioning node_modules.
- Forgetting .env in .gitignore.
- Ignoring npm audit alerts.
Key takeaways
- npm gives access to the world's largest open-source registry: install packages instead of coding everything — a major accelerator.
- package.json = manifest (dependencies, scripts); package-lock.json locks EXACT versions. node_modules NOT versioned (regenerable).
- dependencies (production) vs devDependencies (dev, -D); SEMVER MAJOR.MINOR.PATCH (^ minor/patch, ~ patch).
- npm SCRIPTS standardise commands; npm audit reports vulnerabilities (to watch).
48h challenge — apply tomorrow
Initialise a real project (template above): npm init -y, 1 package + 1 devDependency (-D), 2 scripts, .gitignore (node_modules, .env), then npm audit. 25 minutes is enough.
- I can explain package.json, lock and node_modules.
- I can tell dependencies, devDependencies and semver ^ / ~ apart.
- I have a project installable via npm install + audited.
Frequently asked questions
What should be versioned (Git) in a Node project, and why not node_modules?
Version your code, package.json (the “recipe”: dependencies, scripts) and package-lock.json (exact versions, including sub-dependencies) — plus .gitignore, README and configs. Never version node_modules: it's huge (thousands of files), regenerable with npm install from both manifests, and sometimes platform-specific. Like Salim: share the recipe (json + lock), everyone regenerates the result. Also exclude secrets (.env), logs and temp files.
The npm ecosystem is huge: how to choose good packages?
Not reinventing the wheel is a major asset — but dependencies are also a risk (flaws, varying quality, abandonment). To choose: popularity (downloads, stars — a good signal), active maintenance (recent updates, handled issues), serious documentation, minimal scope (no big package for a trifle). Then manage: keep dependencies up to date (semver understood), watch npm audit, and prefer few proven dependencies over a myriad of unknowns.
What should be versioned in Git for a Node project?