The package.json File
The package.json file is the manifest of your Node.js project. It defines your project's identity, dependencies, scripts, and configuration. Understanding its structure is essential for managing Node.js applications.
Package.json Structure
A complete package.json can have many fields:
{
"name": "my-awesome-app",
"version": "1.0.0",
"description": "An awesome Node.js application",
"main": "src/index.js",
"types": "dist/index.d.ts",
"type": "module",
"scripts": {},
"dependencies": {},
"devDependencies": {},
"peerDependencies": {},
"engines": {},
"keywords": [],
"author": "",
"license": "MIT",
"repository": {},
"bugs": {},
"homepage": ""
}
Essential Fields
name
Your project's identifier:
{
"name": "my-project"
}
Rules:
- Lowercase only
- No spaces (use hyphens or underscores)
- Max 214 characters
- Must be unique if publishing to npm
version
Follows semantic versioning:
{
"version": "1.2.3"
}
- 1 (Major): Breaking changes
- 2 (Minor): New features, backward compatible
- 3 (Patch): Bug fixes
description
A short description for npm search:
{
"description": "A fast HTTP client for Node.js"
}
main
The entry point when your package is required:
{
"main": "src/index.js"
}
// When someone does: require('your-package')
// Node.js loads: your-package/src/index.js
Scripts
Define commands to run:
{
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"build": "tsc",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"format": "prettier --write src/",
"pretest": "npm run lint",
"postbuild": "npm run copy-assets"
}
}
Script Hooks
npm runs pre/post hooks automatically:
npm run build
→ runs "prebuild" (if exists)
→ runs "build"
→ runs "postbuild" (if exists)
Running Scripts
npm run dev # Run "dev" script
npm start # Special: runs "start"
npm test # Special: runs "test"
npm run lint:fix # Run script with colon
Dependencies
dependencies
Packages required in production:
{
"dependencies": {
"express": "^4.18.2",
"mongoose": "^8.0.0",
"dotenv": "^16.0.0"
}
}
devDependencies
Packages only for development:
{
"devDependencies": {
"jest": "^29.7.0",
"typescript": "^5.3.0",
"eslint": "^8.55.0"
}
}
peerDependencies
Packages the user must install (for plugins):
{
"peerDependencies": {
"react": "^18.0.0"
}
}
optionalDependencies
Packages that are nice to have but not required:
{
"optionalDependencies": {
"fsevents": "^2.3.0"
}
}
Version Ranges
{
"dependencies": {
"exact": "4.18.2", // Exactly this version
"caret": "^4.18.2", // >=4.18.2 <5.0.0
"tilde": "~4.18.2", // >=4.18.2 <4.19.0
"greater": ">=4.18.2", // 4.18.2 or higher
"range": ">=4.0.0 <5.0.0", // Between versions
"latest": "*", // Any version
"tag": "latest" // Latest tag
}
}
Engines
Specify required Node.js version:
{
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
}
}
This warns users if their Node.js version is incompatible.
Type Field
Specify module system:
{
"type": "module"
}
"commonjs"(default): Userequire/module.exports"module": Useimport/export
Metadata Fields
author
{
"author": "John Doe <john@example.com> (https://johndoe.com)"
}
Or as an object:
{
"author": {
"name": "John Doe",
"email": "john@example.com",
"url": "https://johndoe.com"
}
}
repository
{
"repository": {
"type": "git",
"url": "https://github.com/username/repo.git"
}
}
bugs and homepage
{
"bugs": {
"url": "https://github.com/username/repo/issues"
},
"homepage": "https://github.com/username/repo#readme"
}
keywords
{
"keywords": ["node", "api", "rest", "express"]
}
license
{
"license": "MIT"
}
Common licenses: MIT, ISC, Apache-2.0, GPL-3.0
Files and Exports
files
What to include when publishing:
{
"files": [
"dist",
"src",
"README.md"
]
}
exports
Modern way to define entry points:
{
"exports": {
".": "./dist/index.js",
"./utils": "./dist/utils.js",
"./package.json": "./package.json"
}
}
Practical Exercise
Common Configurations
TypeScript Project
{
"name": "ts-project",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts"
},
"devDependencies": {
"typescript": "^5.3.0",
"tsx": "^4.0.0",
"@types/node": "^20.0.0"
}
}
Monorepo Workspace
{
"name": "monorepo",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
]
}
Key Takeaways
package.jsondefines your project's identity and configurationnameandversionare required fieldsmainspecifies the entry point for your packagescriptsdefine runnable commands- Use
dependenciesfor production,devDependenciesfor development enginesspecifies required Node.js versiontype: "module"enables ES Modules
Summary
The package.json file is the control center of your Node.js project. You've learned about essential fields like name, version, and main, as well as how to configure scripts, dependencies, and metadata. A well-structured package.json makes your project easier to maintain and share.
Next, you'll learn how to install and use packages in your Node.js projects.

