Skip to content

package.json Explained

package.json is the manifest file at the root of every Node.js project. It describes your project's metadata, dependencies, and scripts. This lesson walks through the fields you will actually use.

What package.json Describes

package.json is a JSON file that npm (and Node.js itself) reads to understand your project: its name and version, which packages it depends on, which module system it uses, and which shortcut commands ("scripts") are available.

You rarely hand-write the whole file. npm init -y scaffolds a sensible default, and npm install/npm uninstall automatically keep the dependencies and devDependencies fields up to date as you work.

{
  "name": "my-api",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "node --watch index.js",
    "test": "node --test"
  },
  "dependencies": {
    "express": "^4.19.2"
  },
  "devDependencies": {
    "eslint": "^9.9.0"
  }
}

This is a minimal but realistic package.json for a small API: it declares ES modules, one production dependency, one dev-only dependency, and three convenience scripts.

Common package.json Fields

name, version, description
type: "module" | "commonjs"
main, exports
scripts { ... }
dependencies { ... }
devDependencies { ... }
engines { "node": ">=22.0.0" }
  • name and version are required if you ever plan to publish the package.
  • "type": "module" makes .js files ES modules; omit it (or use "commonjs") for CommonJS.
  • main (or the more modern exports field) defines the entry point when other code imports your package.
  • engines documents (and can enforce) which Node.js versions your project supports.

package.json Fields Cheatsheet

The fields worth understanding well, even if npm manages most of them for you.

Field Purpose
name Package identifier, required for publishing
version Current version, following SemVer
type "module" for ESM or "commonjs" for CommonJS
scripts Named shortcut commands run via npm run <name>
dependencies Packages required at runtime
devDependencies Packages required only during development
engines Supported Node.js/npm version ranges

The scripts Field

The scripts field maps short names to shell commands, letting your whole team run the same commands consistently instead of memorizing long CLI invocations. A few script names are special: npm start, npm test, and lifecycle hooks like pre/post variants run automatically at the right moment.

{
  "scripts": {
    "start": "node server.js",
    "dev": "node --watch server.js",
    "lint": "eslint .",
    "test": "node --test",
    "build": "node build.js"
  }
}

Run any of these with npm run <name> (e.g. npm run lint), except start and test, which can be run directly as npm start and npm test.

main vs exports

main has long defined a package's entry point for CommonJS require(). The newer exports field is more precise: it can expose multiple named entry points, restrict which internal files consumers may import, and provide different files for CommonJS versus ES module consumers.

Common Mistakes

  • Hand-editing dependencies version numbers without running npm install afterward, causing them to drift from package-lock.json.
  • Forgetting to add "type": "module" and then getting confused by import/export syntax errors.
  • Leaving unused packages in dependencies long after the code that used them was removed.
  • Publishing a package without setting main/exports, leaving consumers unable to import anything useful.

Key Takeaways

  • package.json is the manifest describing your project's metadata, dependencies, and scripts.
  • The type field determines whether .js files are treated as CommonJS or ES modules.
  • scripts provide consistent, memorable shortcuts for common commands across a team.
  • main/exports define what other code sees when it imports your package.

Pro Tip

Add an engines field ({ "node": ">=22.0.0" }) to every project. Combined with npm config set engine-strict true, it stops teammates and CI from silently running your project on an unsupported Node.js version.