package.json
package.json is your project’s identity card and control panel: what it is called, which packages it needs, which version of Node it expects, and the commands you run every day.
On this page · 5 min · Beginner
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Read every common package.json field
- Write npm scripts and run them
- Understand semver ranges like ^1.2.3 and ~1.2.3
- Set the module type and Node engine
Explanation#
name and version identify the package; private: true stops accidental publishing to npm.
"type": "module" makes .js files ES modules (import/export). Without it, Node treats .js as CommonJS (require).
scripts are named commands: "dev": "node --watch server.js". Run them with npm run dev; start and test also work as npm start and npm test.
Semantic versioning MAJOR.MINOR.PATCH: ^5.1.0 allows 5.x.x (no new major), ~5.1.0 allows 5.1.x, 5.1.0 is exact.
"engines": { "node": ">=22" } documents (and with engine-strict, enforces) the Node version. main / exports tell Node which file to load when someone imports your package.
Syntax#
{
"name": "shop-api",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": { "dev": "node --watch server.js", "start": "node server.js", "test": "node --test" },
"dependencies": { "express": "^5.1.0" },
"devDependencies": { "eslint": "^9.0.0" },
"engines": { "node": ">=22" }
}
Code example: Reading package.json and checking semver ranges#
// Node can import JSON with an import attribute
import pkg from './package.json' with { type: 'json' };
console.log(`${pkg.name}@${pkg.version} (type: ${pkg.type})`);
console.log('Scripts:', Object.keys(pkg.scripts).join(', '));
// What does each range allow? A tiny semver check for MAJOR.MINOR.PATCH
function allows(range, version) {
const [maj, min, pat] = version.split('.').map(Number);
const [rMaj, rMin, rPat] = range.replace(/[\^~]/, '').split('.').map(Number);
if (range.startsWith('^')) return maj === rMaj && (min > rMin || (min === rMin && pat >= rPat));
if (range.startsWith('~')) return maj === rMaj && min === rMin && pat >= rPat;
return version === range;
}
for (const v of ['5.1.0', '5.1.9', '5.4.2', '6.0.0']) {
console.log(v.padEnd(6), '^5.1.0:', allows('^5.1.0', v), ' ~5.1.0:', allows('~5.1.0', v));
}
// package.json used for this example:
// { "name": "shop-api", "version": "1.0.0", "type": "module",
// "scripts": { "dev": "node --watch server.js", "start": "node server.js", "test": "node --test" } }
shop-api@1.0.0 (type: module) Scripts: dev, start, test 5.1.0 ^5.1.0: true ~5.1.0: true 5.1.9 ^5.1.0: true ~5.1.0: true 5.4.2 ^5.1.0: true ~5.1.0: false 6.0.0 ^5.1.0: false ~5.1.0: false
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- import ... with { type: "json" } loads package.json as an object.
- scripts lists the commands you can run with npm run <name>.
- ^5.1.0 accepts any 5.x version from 5.1.0 up — minor and patch updates.
- ~5.1.0 accepts only patch updates within 5.1.x.
- Neither accepts 6.0.0: a new major version may contain breaking changes.
Real-world use case#
A project’s scripts become its documentation: npm run dev, npm test, npm run lint, npm run db:migrate. New developers learn the workflow by reading one file.
Common mistakes#
import statements in .js files fail with “Cannot use import statement outside a module”.
Any future release, including breaking majors, can be installed. Use ^ or exact versions.
package.json is committed. Read secrets from environment variables, not from script lines.
Best practices#
- Set "private": true for apps
- Use scripts for every common task
- Declare engines.node
- Keep dependencies lean and up to date
Remember this#
^ = same major. ~ = same minor. exact = exact.
npm run <script> (npm start / npm test shortcuts).
"type": "module" → import/export in .js.
Practice exercise#
Your task: Write a scripts section with dev (node --watch server.js), start (node server.js), test (node --test) and lint (eslint .).
Need a hint?
Show solution
{
"scripts": {
"dev": "node --watch server.js",
"start": "node server.js",
"test": "node --test",
"lint": "eslint ."
}
}
Mini quiz#
Which versions does "^2.3.0" allow?
Want more? Practise all Node.js MCQs · Node.js interview questions
My notes#
Saved in this browser.