Question presented to candidate: "Two developers run npm install against the identical package.json on different days. What guarantees they end up with the same dependency versions, and what file makes that guarantee possible?"
What a strong answer should cover:
package.jsondeclares dependency ranges (^4.17.20);package-lock.jsonrecords the exact version actually resolved for every dependency and transitive dependency in the tree, plus its exact source (a tarball URL and integrity hash).- 📌 This is what makes installs reproducible across machines and over time — without it, two installs run on different days could resolve a range like
^4.17.20to two different actual patch/minor versions if a new one had been published in between. package-lock.jsonshould be committed to version control — it is not a generated artifact to.gitignore, precisely because its entire value is being a shared, exact record everyone installs from.npm ci(distinct fromnpm install) installs strictly from the lock file, deletesnode_modulesfirst, and errors out ifpackage.jsonandpackage-lock.jsonare out of sync — this is why CI pipelines usenpm ci, notnpm install, for reproducible builds.- The lock file also carries an integrity hash (a checksum) for each resolved package, which npm verifies against the downloaded tarball — a defense against a compromised or tampered registry response, not just a version-pinning mechanism.
- A precise answer distinguishes "the lock file's job" from "npm's dependency-resolution algorithm" — the lock file is the recorded result, not the resolver itself; understanding it as a recorded artifact (rather than something that itself does the resolving) avoids a common conceptual muddle.
Clarifying questions expected:
- "Is the concern reproducibility across developer machines, or reproducibility in CI/CD specifically?" — both are solved by the same mechanism, but the answer's emphasis can differ.
- "Yarn or pnpm instead of npm?" — each has its own equivalent lock file format (
yarn.lock,pnpm-lock.yaml) serving the identical purpose.
Code / implementation expected: Optional — inspecting a real, freshly generated package-lock.json's structure (the exact version and tarball URL it records) makes the concept concrete rather than abstract.