npm#
npm (Node Package Manager) is the package manager that ships with Node.js. Its job
is to fetch third-party code from a public registry and place it in your project’s
node_modules/ folder so your tools and app can use it.
npm vs Vite — Different Jobs, Different Moments#
This distinction is critical:
npm runs before any building. It gets dependencies onto your disk.
Vite runs after npm. It assumes dependencies are already there and bundles them.
npm is the librarian. Vite is the builder. They never overlap.
npm install # fetch everything in package.json → node_modules/
npm run dev # start Vite's dev server (Node executing Vite's JS)
npm run build # produce the final dist/ bundle
The package.json Contract#
package.json is a declaration of intent — it lists what your project needs and
what versions are acceptable. It is not an enforcement mechanism.
{
"dependencies": {
"react": "^18.0.0",
"three": "^0.160.0"
},
"devDependencies": {
"vite": "^5.0.0",
"typescript": "^5.0.0"
}
}
dependencies are libraries that end up in the browser bundle (React, Three.js). devDependencies are tools only needed during development — they never reach the browser (Vite, TypeScript, ESLint).
Note
package.json declares intent. What’s actually installed and what actually runs
is whatever is on disk in node_modules/. If you run npm install after
changing a version, npm overwrites the folder to match. If you skip npm install
entirely, nothing works — the files don’t exist.
node_modules/#
Every project carries its own copy of all dependencies in node_modules/. This
means two projects on the same machine can use different versions of React with zero
conflict — each has its own copy.
The tradeoff is size. A simple React project can accumulate 200mb+ in node_modules/
because of nested dependencies of dependencies. This folder is never committed to
git (it’s in .gitignore by default) — it’s always reconstructed from
package.json and package-lock.json via npm install.
# First thing to do after cloning any JS project
npm install
package-lock.json#
While package.json allows version ranges (^18.0.0 means “18.x.x”),
package-lock.json records the exact versions that were actually installed.
This ensures that npm install produces identical results on every machine and
at any point in time. Always commit the lockfile.
npx — Running Without Installing#
npm ships with a companion tool called npx, which executes packages temporarily without permanently installing them. This is how project scaffolding works:
npx create-vite my-app
npx fetches create-vite from the registry, runs it once to scaffold your project
files, then discards it. The scaffolded package.json already lists Vite as a
dependency — but Vite itself is not installed yet. That happens when you then run
npm install.
Note
npm create vite is a modern alias for npx create-vite. They do the same
thing. The full sequence for a new project is always:
npx create-vite my-app # scaffold files + package.json
cd my-app
npm install # actually download Vite + React + everything
npm run dev # now it works
Bundle Size and devDependencies#
npm tracks which packages are devDependencies vs dependencies. Vite uses this
distinction during the build: dev dependencies are excluded from the final browser
bundle. Vite, TypeScript, and ESLint never appear in what users download — they did
their job at build time and are gone.