Reference

package.json fields

Every field, and which ones can be left alone

This reference page covers the fields that appear in a package.json file for a front-end project, what each one controls, and which ones you can leave alone.

A Complete File

package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "description": "A short sentence about the project",
  "private": true,
  "type": "module",
  "main": "index.js",
  "scripts": {
    "dev": "http-server -p 3000",
    "build": "node scripts/build.js",
    "start": "npm run build && npm run dev"
  },
  "dependencies": {},
  "devDependencies": {
    "http-server": "^14.1.1"
  },
  "keywords": [],
  "author": "Your Name",
  "license": "MIT"
}

Only name and version are strictly required, and even those matter mainly to packages that get published. A project that stays private can carry a mostly empty file and work perfectly.

Identity Fields

name

The name must be lowercase with no spaces, though hyphens are fine. It defaults to the folder name. For a published package, this name must be unique across the registry, but for a private project it acts as a simple label.

version

This field uses three numbers separated by dots, representing major, minor, and patch releases. It is meaningful for published packages, but for a private website it serves as decoration.

description

This is a one-sentence description shown on the registry page for published packages. It is harmless and useful to fill in for any project.

author, license, keywords

These are metadata fields for the registry. The command npm init -y fills the license field with ISC, which is a real open source license but might not be the one you want. You can set it deliberately or configure the project as private instead.

Behavior Fields

private

When this is set to true, npm refuses to publish the project to the public registry. Setting this is best for any private project to prevent accidental publishing.

type

When this is set to "module", the .js files in the project use import and export. Omitting this field makes files use the older require style. Mixing these two patterns produces confusing error messages about unexpected tokens.

main

This field specifies the entry point of the package when imported by another project. The npm init command writes this field whether the target file exists or not, and it remains irrelevant for a website that is not imported.

engines

This field specifies the Node versions that the project supports. Deploy platforms read this to select a matching Node runtime, which makes it useful.

browserslist

This field indicates which browsers to support. Several build tools read it to decide how far to translate modern CSS and JavaScript. It is absent unless a tool explicitly requests it.

workspaces

This field configures repositories that hold several packages at once. A single website project does not need it.

scripts

Scripts are a set of named shortcuts. Each value is a command handed to the shell, so shell features like &&, >, and | work inside them.

Inside a script, commands installed into node_modules are found automatically. That is the reason scripts exist rather than typing the tool's name directly.

npm run name

This command runs the script called name, and works for any script.

npm start and npm test

These are two script names npm treats specially. They run without the word run, whereas other scripts require it.

npm run with no name

This command lists every script defined in the file. It is the fastest way to see what a freshly cloned project can do.

Scripts calling scripts

A value like "start": "npm run build && npm run dev" is common and encouraged. Building the big step out of small named ones keeps things organized.

pre and post prefixes

A script named prebuild runs automatically before build, while postbuild runs afterward. This behavior is convenient, but it is easy to miss when reading a file.

Quoting

The value is JSON, so a quote mark inside it has to be escaped with a backslash. This is the usual source of a script that looks right and behaves wrong.

dependencies And devDependencies

dependencies

This is code that the finished product needs at runtime. Running npm install name adds packages here.

devDependencies

These are tools used only while developing or building. Running npm install --save-dev name adds packages here, and nearly everything in a static site project belongs in this list.

peerDependencies

This list is used by plugins to specify which host packages they attach to. You will usually read this in other files rather than writing it yourself.

optionalDependencies

These are optional packages whose install failure does not stop the installation. Using this list is rare.

Version Range Syntax

The string next to a package name is a rule about which versions are acceptable, not a fixed choice. The exact version that got installed lives in package-lock.json.

What the prefixes mean:
"^14.1.1"    minor and patch updates allowed: 14.9.9 yes, 15.0.0 no
"~14.1.1"    patch updates only: 14.1.9 yes, 14.2.0 no
"14.1.1"     exactly this version, nothing else
"*"          any version at all (avoid)

The caret is npm's default because semantic versioning promises that minor and patch releases do not break existing behavior. That promise is a convention rather than an enforced rule, which is one more reason the lock file gets committed.

Files That Sit Next To It

package-lock.json

npm generates this file. It records the exact resolved version and an integrity checksum for every package. You do not hand-edit this file, but you do commit it.

node_modules/

This folder contains the downloaded packages themselves. You can rebuild it from the files above, and it is never committed.

.npmrc

This file holds npm configuration for the project. Most projects do not have one.

.gitignore

This is a git configuration file rather than an npm file, and it is where you exclude node_modules and the build output folder from git.