Versions and Lockfiles
The site builds perfectly on your laptop. On your teammate's laptop, cloned the same afternoon, the date picker looks different and one button is broken. Same package.json, different code. The cause is version ranges, and the cure is a file most beginners ignore: the lockfile.
The rule
package.jsonallows a range; the lockfile pins the exact versions.
Semantic versioning. Package versions are written MAJOR.MINOR.PATCH, like 4.6.13:
- PATCH (4.6.13): bug fixes only.
- MINOR (4.6.13): new features that should not break existing code.
- MAJOR (4.6.13): breaking changes; your code may need updating.
Ranges. package.json usually holds a range, not one exact version:
| Written | Accepts | Example matches |
|---|---|---|
4.6.13 |
exactly that version | 4.6.13 only |
~4.6.13 |
patch updates | 4.6.14, 4.6.20, but not 4.7.0 |
^4.6.13 |
minor and patch updates | 4.7.0, 4.9.2, but not 5.0.0 |
^ is npm's default. It trusts package authors to follow the rules, which they usually, but not always, do. (For versions starting with 0., npm treats ^ more cautiously, since anything can change before 1.0.)
The lockfile. When npm installs, it writes package-lock.json, recording the exact version of every package in the tree, including the packages your packages depend on. The next npm install follows the lockfile instead of picking the newest matching version. Commit it to Git, so everyone, and every deployment, gets identical code.
Two install commands.
npm installinstalls and may update the lockfile ifpackage.jsonchanged.npm ci("clean install") deletesnode_modulesand installs exactly what the lockfile says. If the lockfile andpackage.jsondisagree, it stops with an error rather than guessing. Build servers use it for exactly that strictness.
Updating on purpose. npm outdated lists packages with newer versions; npm update moves them within their ranges. Crossing a major version is a deliberate step: read the package's changelog, then install the new major and test.
The shortcut
To check a version against a range, look at the symbol and freeze the digits to its left: ^ freezes the first number, ~ freezes the first two. Anything to the right may rise.
Range ^4.6.13
^freezes the major, 4. The candidate keeps 4 and is at least 4.6.13, so it matches.
The trap is adding package-lock.json to .gitignore because it looks like generated noise. That is exactly how two laptops end up with different code.
Drills
Answer fast — trust the rule.
A package goes from 2.3.1 to 3.0.0. What does that signal?
Which version does ^2.3.1 NOT accept?
Which version does ~2.3.1 accept?
Should package-lock.json be committed to Git?
A build server should install exactly what the lockfile says and fail if it is out of date. Which command?
Remember
package.jsonallows a range; the lockfile pins the exact versions.- Freeze the digits left of the symbol:
^freezes one,~freezes two. - Trap: ignoring the lockfile lets every laptop drift to different code.
