Blog
3 min read

npm run dev vs npm run build vs npm start: What Each One Does

npm run dev starts a development server with hot reload; npm run build makes an optimised production version; npm start runs that production version. What each does, where the commands come from in package.json, and why you should never run dev mode in production.

Almost every JavaScript project has three commands you'll see over and over: npm run dev, npm run build and npm start. They do very different jobs.

Where these commands come from

They're defined in the "scripts" section of your package.json. (What are npm and package.json?) A typical Next.js project:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint ."
  }
}

npm run dev simply runs whatever is next to "dev". A Vite project might have "dev": "vite" and "build": "vite build". The names are conventions — check your own package.json to see what they actually do.

(npm start and npm test are special: you can leave out run.)

npm run dev — for working on the app

Starts a development server, usually at http://localhost:3000 or 5173. (What is localhost?)

  • Hot reload — save a file and the browser updates instantly.
  • Helpful errors — detailed messages and overlays.
  • Unoptimised — code isn't minified; pages may compile on first visit.
  • Slower and heavier than production, by design.

This is what you run while building.

npm run build — make the production version

Creates an optimised version of your app, ready to deploy:

  • Compiles TypeScript and JSX into plain JavaScript
  • Minifies and bundles code, splits it into chunks, adds hashed file names
  • Pre-renders static pages (in frameworks like Next.js and Astro)
  • Fails if there are type errors or broken imports

The output goes into a folder like dist/ (Vite) or .next/ (Next.js). It doesn't run anything — it just produces files.

npm start — run the production version

Runs the built app as a production server. For Next.js that's next start, which serves the .next/ build. For a Node/Express API it's often node server.js.

Pure front-end apps (plain React + Vite) usually don't have a production server at all: the dist/ folder is static files you upload to a host or serve with Nginx. vite preview lets you check the build locally. (Deploy a React app)

Side by side

npm run dev npm run build npm start
Purpose Develop Prepare for production Run in production
Hot reload Yes — No
Speed Slow, unoptimised — Fast, optimised
Output A running dev server Files (dist/, .next/) A running production server
Use on a live server? No Yes, before start Yes

Don't run dev mode in production

It's surprisingly common — especially with AI-built apps — to see npm run dev running on a live server. Problems:

  • Much slower and uses far more memory
  • Shows detailed error messages (and sometimes source code) to visitors
  • Not designed to stay up under real traffic

On a server, the sequence is npm ci → npm run build → npm start (kept running by a process manager). (PM2 vs systemd, Deploy a Node.js app to a VPS)

When build fails but dev works

This happens a lot: dev mode is forgiving, the production build is strict. Type errors, lint errors, case-sensitive imports and missing environment variables often only show up in build. (npm run build fails but dev works)

Run npm run build locally before deploying — it catches most deploy failures in seconds.


EasySpawn builds your app and runs the production version for you — the right command, kept running, with HTTPS in front — so dev mode never ends up on your live site. See how it works or join the waitlist.

Related: What Are npm and package.json? · npm run build Fails but Dev Works · Dev, Staging, and Production Explained · Webpack vs Vite

Keep reading