Afhankelijkheden
Wat is een lockfile?
Een lockfile legt de exacte versie vast van elke afhankelijkheid die een pakketbeheerder heeft opgelost, direct en transitief, zodat de volgende installatie dezelfde boom krijgt. Het is het beste plan dat u voor een build hebt. Het legt niet vast wat de build daadwerkelijk heeft gebruikt.
Bijgewerkt op
Wat een lockfile vastlegt
Uw manifest, zoals package.json of pyproject.toml, somt de pakketten op waarvan u afhankelijk
bent en de versiebereiken die u accepteert. De pakketbeheerder zet die bereiken om in exacte versies voor de hele boom,
inclusief transitieve afhankelijkheden, en schrijft het resultaat naar de
lockfile. De documentatie van npm zegt dat package-lock.json "the exact tree that was generated, such that
subsequent installs are able to generate identical trees" beschrijft.
Eén vermelding in package-lock.json ziet er zo uit:
"node_modules/raw-body": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-...",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
}
}
- version is de exact gekozen versie.
- resolved is waar hij is opgehaald: een tarball-URL van een registry, of een git-URL met een commit.
- integrity is een Subresource Integrity-hash van de tarball, zodat een gemanipuleerde download mislukt.
- dependencies zijn de eigen afhankelijkheden van het pakket, en zo wordt de boom, of dependency graph, aan elkaar geregen.
Lockfiles per pakketbeheerder
| Pakketbeheerder | Lockfile | Installeren zonder hem te wijzigen |
|---|---|---|
| npm | package-lock.json | npm ci |
| Yarn (Berry) | yarn.lock | yarn install --immutable |
| pnpm | pnpm-lock.yaml | pnpm install --frozen-lockfile |
| uv | uv.lock | uv sync --locked |
| Poetry | poetry.lock | poetry install |
| Cargo | Cargo.lock | cargo build --locked |
| Bundler | Gemfile.lock | bundle config set frozen true |
| Go modules | Versies in go.mod en checksums in go.sum |
Buildopdrachten werken go.mod standaard niet bij |
Met alleen pip is een requirements.txt met exacte versies de gebruikelijke vervanger. Die pint vast wat erin
staat, maar alles wat erbuiten blijft, wordt bij elke installatie opnieuw opgelost.
Gebruik frozen installs in CI
Een lockfile helpt alleen als de build ermee installeert. Een gewone npm install kan
package-lock.json bijwerken als die niet meer overeenkomt met package.json, zodat de build
ongemerkt een nieuwe boom oplost. npm ci is gemaakt voor geautomatiseerde omgevingen:
- Het vereist een
package-lock.jsonofnpm-shrinkwrap.json. - Als de lockfile en
package.jsonniet overeenkomen, stopt het met een fout in plaats van de lockfile bij te werken. - Het verwijdert eerst een eventueel bestaande
node_modules. - Het schrijft nooit naar
package.jsonof de lockfile.
De andere opdrachten in de tabel hierboven doen hetzelfde voor hun pakketbeheerders.
Applicaties en bibliotheken
Commit de lockfile voor applicaties en alles wat u uitrolt. Bij bibliotheken vergrendelt hij alleen uw eigen
ontwikkeling en CI: npm publiceert package-lock.json nooit en negeert het bestand overal behalve in het
hoofdproject. De applicaties die uw bibliotheek installeren, lossen de afhankelijkheden daarvan zelf op, binnen uw
versiebereiken. De enige uitzondering bij npm is npm-shrinkwrap.json, dat wel wordt gepubliceerd en voorrang
krijgt, en dat de meeste bibliotheken niet zouden moeten gebruiken.
Waarom een lockfile niet vastlegt wat is geleverd
Een lockfile is het plan voor één pakketbeheerder in één project. De build die uw release opleverde, deed meer dan dat plan volgen:
- Hij is misschien niet gebruikt. Een installatie die niet frozen is, een ontbrekende lockfile of een tweede lockfile in een monorepo betekent dat de boom anders is opgelost dan het bestand waar u naar kijkt.
- Caches. Pakketten die uit een CI-cache worden teruggezet, worden geïnstalleerd zonder te worden opgehaald, en een cache die via een gedeeltelijke sleutel is teruggezet, kan ouder zijn dan de huidige lockfile. Zie wat de GitHub Actions-cache verbergt.
- Buildtools. Setup-actions, compilers, linters en codegeneratoren komen via andere kanalen binnen, met hun eigen afhankelijkheidsbomen.
-
Downloads en installatiescripts. Een
curlin een buildstap of het installatiescript van een pakket haalt code op die in geen enkele lockfile staat. - Base images. Een containerbuild haalt images en besturingssysteempakketten op die buiten elke lockfile voor een programmeertaal vallen.
De integrity-hashes helpen hierbij niet. Ze bewijzen dat er niet met de pakketten in de lockfile is geknoeid; ze zeggen niets over wat de build daarbuiten heeft opgehaald. SCA-tools die een lockfile omzetten in een SBOM, erven dezelfde blinde vlekken.
Leg de build vast, behoud de lockfile
Blijf lockfiles committen en ermee installeren via frozen installs. Ze maken builds herhaalbaar. Voor de vastlegging van wat een release bevat, legt CRACI de build zelf vast: een proxy op de GitHub Actions-runners van CRACI die pakketten herkent, legt elk pakket vast dat elke job ophaalt, inclusief pakketten die uit CI-caches zijn teruggezet, en de SBOM van elke job vermeldt zijn eigen volledigheid. Die vastlegging geeft een completer beeld van de gebruikte afhankelijkheden dan een scan van de lockfile. Zie SBOM's tijdens de build, of boek een demo om de twee te vergelijken op een van uw eigen builds.
Lockfiles: veelgestelde vragen
Wat is een lockfile?
Een lockfile is een bestand dat een pakketbeheerder schrijft om de exacte versie vast te leggen van elke afhankelijkheid die hij heeft opgelost, direct en transitief, samen met de herkomst en een checksum. Latere installaties lezen het bestand om dezelfde boom te reproduceren in plaats van versiebereiken opnieuw op te lossen.
Moet ik mijn lockfile committen?
Ja, voor applicaties en alles wat u uitrolt. Zonder gecommitte lockfile lost elke schone installatie versiebereiken opnieuw op en kan die nieuwe transitieve versies binnenhalen. Commit de lockfile en installeer ermee via een frozen install zoals npm ci in CI.
Pint een lockfile transitieve afhankelijkheden vast?
Ja. Dat is zijn belangrijkste taak. Het manifest noemt alleen uw directe afhankelijkheden en hun toegestane bereiken; de lockfile legt de exact gekozen versie vast van elk pakket in de boom.
Gelden lockfiles voor bibliotheken die ik publiceer?
Niet voor uw gebruikers. npm bijvoorbeeld publiceert package-lock.json nooit en negeert het bestand overal behalve in het hoofdproject. De applicaties die uw bibliotheek installeren, lossen de afhankelijkheden daarvan zelf op, binnen de bereiken die uw package.json toestaat.
Wat doet het integrity-veld in package-lock.json?
Het bevat een Subresource Integrity-hash, meestal sha512, van de pakkettarball. npm controleert het gedownloade pakket daartegen, zodat de installatie van een gemanipuleerde tarball voor een vergrendelde versie mislukt. Het beschermt de pakketten in de lockfile, niet wat de build daarbuiten ophaalt.
Is een lockfile hetzelfde als een SBOM?
Nee. Een lockfile is invoer: het plan dat een pakketbeheerder voor één project volgt. Een SBOM is een inventaris van een release. SCA-tools zetten een lockfile vaak om in een SBOM, wat werkt als de build exact de lockfile heeft geïnstalleerd en verder niets.
Vergelijk uw lockfile met uw build
Draai één workflow op CRACI en leg de vastgelegde SBOM van opgehaalde pakketten naast wat uw lockfile zegt.
Demo boeken