Coming from Enterprise Development and a history of Startups, when I first started getting into Typescript and dealing with package managers, I was a bit shocked to find the default in nearly all package managers is to use the latest minor or patch version of libraries. On an enterprise team, this results in 10 developers all having different setups. It also results in surprise production bugs. I see from the following article, that more and more people are learning the lessons that Java/Ivy/Maven learned so many years ago.
When you have 40 libraries that you depend on, what are the mathematical chances that one of those libraries will introduce a bug in a patch or minor version update in the next week. Perhaps minimal. What are the chances over the next 5 years. My guess would be near 100% in this case. Enjoy fighting that fire
Many do this minor or patch version auto-update with the belief of "I get free bug fixes and free security patches". If you have a well-tested app, and have done penetration testing from your security team or 3rd party provider, then you are bug free and not using the paths of the library that had the bugs anyways. Worse, sometimes a bug fix in a library breaks your application because the developer worked around it. Then, finally, even worse is the security team screaming at you that penetration testing was not re-run when libraries were 'automatically updated'. In reality, you will not be saved by auto-upgrade by any security bug like the log4j incident which had to be dealt with when I was at Twitter. In fact, Twitter had to wait or fork log4j and patch themselves and release rather than auto-upgrade. (auto-upgrades for security patches just don't work).
I still do not understand why the default npm, yarn, pnpm is not set to "save-exact=true" in the .npmrc file forcing junior developer teams scratching their heads as I hear comments of
Well, it works for me
There are much better automated upgrade solutions where you can have an automated workflow do the upgrade as part of a commit to the repository so let's talk about that next.
Let's say you have a production incident today and you look and find the git hash of what is in production. You checkout that git hash and you run 'npm install'. Everything you now have on your machine now matches production 100%, correct? Wrong unless of course you set 'save-exact=true'. This leads to cases of I can't reproduce the bug further slowing down the team.
Let's take a different approach and set save-exact=true. Now, every git commit on the master branch, you can checkout and run 'npm install' and end up with the exact code and exact library versions.
If you still really want automatic upgrades, eventually move to on of the systems that does Pull Requests so that all version changes end up as part of a commit. In this way, you can do what is called a git bisect and there have been plenty of times at Twitter where a git bisect ended up being a library version change. It is GREAT that Twitter locks all it's versions in the monorepo to be completely fixed.
When Java was 5 years old
In general, Typescript is great allowing me to work in web, backend, mobile with one language for everything. The downside is that it feels like Java felt when it was 5 years old. It is like reverting 15 years of practices that were discovered along the way. I still think it is the right direction. Here is another example from the java world. In Java, it is well known the jdk 99.9% of the time never introduces a JVM with breaking changes and the JVM is not checked into the git repository. While the JVM is not, a gradle wrapper around the build system with a version of the build system is checked in. With this in place, I can go back 1 year ago and run a build and it uses a build system version that was used 1 year ago. That is how advanced it has gotten over the years.
Npm at least has "engine-strict=true" which is definitely advised so when you upgrade your team, you enforce everyone using the same version.
In summary, I am excited by Typescript but it still has quite a ways to go.