What is the `package.json` for, and what do its most important fields like `scripts`, `main`, and `type` do?
Show answer — try answering out loud first
The package.json is the identity and configuration file of a Node project. It describes the project (name, version, description), states its entry file (main), which dependencies it needs (dependencies and devDependencies), which commands can be run (scripts, which you run with npm run <name>), and which module system it works in (type: "commonjs" or "module").
Think of the package.json as the project's "ID card". npm and Node read it to know what to install, how to start, and how to treat the code. The key fields:
name: the package's name. Lowercase, no spaces. If you published to npm, this would be its identifier.version: the project's current version, inmajor.minor.patchformat (semver), for example1.4.2.description: a short sentence explaining what the project is about.main: the entry point. It's the file that gets loaded when someone doesrequire('your-package'). It defaults toindex.js.scripts: an object with command shortcuts. Each key is a name and its value is the terminal command that runs. You run them withnpm run <name>(for examplenpm run dev). Some names have their own shortcut:startandtestcan be run asnpm startandnpm test, without therun.dependencies: the packages your app needs in production to work (for exampleexpress).devDependencies: the packages you only use during development (for examplenodemon,eslint,vitest). They aren't needed once the app is running on the server.type: defines the default module system. With"commonjs"(or if you omit it) you userequire/module.exports. With"module"you useimport/export(ESM).
About scripts in more detail: when you run npm run dev, npm looks for the "dev" key inside scripts and runs that command in a shell, also adding the binaries from node_modules/.bin to the PATH. That's why you can write nodemon or eslint in a script even though they aren't installed globally.
A real package.json (remember: JSON doesn't allow comments, so below the JSON is clean and the explanation of each field goes separately).
{
"name": "mi-api",
"version": "1.0.0",
"description": "API REST de ejemplo con Express",
"main": "src/index.js",
"type": "commonjs",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"test": "vitest run",
"lint": "eslint ."
},
"dependencies": {
"express": "^4.19.0"
},
"devDependencies": {
"nodemon": "^3.1.0",
"vitest": "^1.6.0",
"eslint": "^9.0.0"
}
}
What each part of that file does:
name/version/description: identify the project and its current version.main: doingrequire('mi-api')loadssrc/index.js.type: "commonjs": the project usesrequireandmodule.exports.scripts.start:npm startstarts the app in normal mode withnode.scripts.dev:npm run devstarts withnodemon, which restarts the server when you save changes.scripts.test:npm testruns the tests with Vitest.scripts.lint:npm run lintchecks the code style with ESLint.dependencies:expressis needed in production.devDependencies:nodemon,vitest, andeslintare only used while developing.
How those commands look in the terminal:
npm start # runs the "start" script (shortcut, no "run")
npm test # runs the "test" script (shortcut, no "run")
npm run dev # runs the "dev" script (custom names need "run")
npm run lint # runs the "lint" script
Putting comments inside the package.json. JSON does not allow comments (// or /* */), and if you add them, npm will fail to read the file with a parse error. Another common mistake is trying to run a custom script without run, for example writing npm dev instead of npm run dev; only start, test, stop, and restart have a direct shortcut, everything else always needs run.
"The package.json is the project's configuration and identity file. It stores the name, the version, and the description, defines the entry point in main, and separates dependencies into dependencies, which are the production ones, and devDependencies, which are the development ones. In scripts I put command shortcuts that I run with npm run, like npm run dev to bring up the server with nodemon; start and test have their own shortcut and don't need the run. And the type field decides the module system: commonjs for require, or module for import and export. One important thing: JSON doesn't allow comments, so you should never put // inside the file."
You have these scripts in your package.json. Which command runs each one correctly?
{
"scripts": {
"start": "node app.js",
"seed": "node scripts/seed.js"
}
}
See answer
startcan be run asnpm start(it has a shortcut) or also asnpm run start.seedis a custom name, so it needsrun:npm run seed. Writingnpm seedwould error because npm doesn't recognize it as a command.