package.json does more than list your dependencies: it also defines scripts (shortcuts for running long commands). And alongside it, the lockfile guarantees that your install is reproducible.
Scripts in package.json
The scripts section of package.json defines command aliases:
{
"scripts": {
"dev": "vite --port 3000",
"build": "vite build",
"preview": "vite preview",
"test": "vitest",
"lint": "eslint . --ext .ts,.tsx",
"typecheck": "tsc --noEmit",
"format": "prettier --write ."
}
}Running a script
With pnpm:
pnpm shorthand (without run):
With bun:
With npm:
Special scripts: pre and post
pnpm and npm recognize pre and post prefixes to run scripts before and after another:
{
"scripts": {
"prebuild": "pnpm typecheck",
"build": "vite build",
"postbuild": "node scripts/compress-assets.js"
}
}pnpm build will automatically run prebuild, then build, then postbuild.
The role of the lockfile
Your package.json declares version ranges (^18.3.0). But when you run pnpm install, pnpm resolves those ranges and installs exact versions.
The lockfile records these exact versions:
# excerpt from pnpm-lock.yaml
react:
specifier: ^18.3.0
version: 18.3.1Without a lockfile, two developers who clone the same project two days apart could install different versions if a package was updated in between. With the lockfile, everyone has exactly the same versions.
The three lockfiles
| Package manager | Lock file | Format |
|---|---|---|
| npm | package-lock.json | Human-readable JSON |
| pnpm | pnpm-lock.yaml | Human-readable YAML |
| bun | bun.lockb | Binary |
One lockfile per repo
If you see two lockfiles in the same project (package-lock.json AND pnpm-lock.yaml), there is a problem. Someone ran the wrong package manager. Delete one of them (and node_modules/) and reinstall with the correct manager.
The command to clean up before migrating to pnpm:
pnpm lockfile format