- Bad: Lockfiles in packages breaks semantic versioning.
- Good: Lockfiles in apps breaks semantic versioning.
I’ve no issue using a lockfile in apps, it’s a good thing, that’s the end of talking about apps.
I love Semantic Versioning no matter the language, but today I’m writing about npm modules and what lockfiles mean to semantic versioning for packages.
There are two common schools of thought, the first here from the prolific opensource contributor Sindre Sorhus, on his AMA he writes:
“Lockfiles for apps, but not for packages. Lockfiles are great for apps where you want a controlled reproducible environment, but for packages this doesn’t make much sense. The
package-lock.jsonfiles in dependencies are ignored, so the lockfile only applies when users run
npm installin the package repo. If you use a lockfile for packages, your local dependency tree will not match the dependency tree of users having your package as a dependency. This can potentially cause problems if one of your package dependencies breaks your package in a patch release. The lockfile will prevent you from seeing the problem locally, but it will affect your users.”
The counter-argument to the above is Yarn’s take on the subject, that everything should include a lockfile, it’s a bit of a read, I’ll wait here.
My retort to Yarn’s argument linked is as I stated in my opening, Lockfiles breaks semantic versioning, if you use a lockfile there is no semantic versioning and using
^ for modules in `package.json` is superfluous.
Yarn suggests that the updating of dependencies is a burden, it is, but not how Yarn sees it IMHO, we have tests that are tested in Travis CI, when not caching npm dependencies at Travis CI a fresh install of the dependencies takes place for each new pull request or commit and triggers a Travis CI build to which Travis CI installs these latest dependencies based on the semantic version range of the package in question. If there are errors, the build fails and can then be investigated further.
Doing it the Yarn way sees no automation or way of respecting semantic versioning for modules, everything becomes a manual process, either a user (“User Burden”) or a contributor (“Contributor Burden”) comes into play, either the user, who would, in fact, become a contributor has to make a conscious decision to start the manual process of checking for and updating a package’s dependencies.
Yarn’s closing summarizes that without lockfiles everything is more complicated, also suggesting there should be improved tools to make the automatic upgrading of packages painless, it makes sense right up until you try to work out where semantic versioning fits into this equation, it doesn’t, Yarn locks everything down to a specific version negating all semantic versioning.
Semantic versioning isn’t foolproof, it’s not perfect, humans make mistakes, I’ve made plenty and released a patch version moments later after noticing, if I didn’t notice myself and it is brought to my attention sometime later I release a patch version. Any other packages that are consuming my package have a hands free update waiting for them with their next CI build or deployment without the need for human intervention.