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.

See also

Node.js — the runtime npm and all installed packages run on. Vite — what runs after npm has done its job.