Packages upgrade examples
And upgrading any package, even to a
patch
version, can result in a completely broken app.In order to reduce risks associated with packages, we've made some very opinionated decisions about how to handle our dependencies, by default.
Those decisions are based on years of experience with production systems, and are meant to avoid breaking production apps unexpectedly.
First of all, we only install fixed versions.
For example, "@amplitude/react-amplitude": "1.0.0"
, the "1.0.0"
is a fixed version, it won't change unless we manually/expressively do it.
We don't use any automation like "^1.0.0"
or ">1.0.0"
Also, we configured NPM/Yarn to always install fixed versions by default using npm config set save-exact true
This alone reduces the risks tremendously. Coupled with
yarn.lock
file, it makes your deployments much safer.In order to simplify packages upgrade, we provide a small utility tool (which is nothing more than an alias to a yarn
command that too few people know about).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
yarn packages:upgrade
yarn run v1.22.0
$ yarn upgrade-interactive --latest
info Color legend :
"<red>" : Major Update backward-incompatible updates
"<yellow>" : Minor Update backward-compatible features
"<green>" : Patch Update backward-compatible bug fixes
? Choose which packages to update. (Press <space> to select, <a> to toggle all, <i> to invert selection)
devDependencies
name range from to url
❯◯ @next/bundle-analyzer latest 9.4.1 ❯ 9.4.2 https://github.com/vercel/next.js#readme
◯ @types/jest latest 25.2.2 ❯ 25.2.3 https://github.com/DefinitelyTyped/DefinitelyTyped.git
◯ @typescript-eslint/eslint-plugin latest 2.33.0 ❯ 3.0.0 https://github.com/typescript-eslint/typescript-eslint#readme
◯ @typescript-eslint/parser latest 2.33.0 ❯ 3.0.0 https://github.com/typescript-eslint/typescript-eslint#readme
◯ cypress latest 4.5.0 ❯ 4.6.0 https://github.com/cypress-io/cypress
◯ eslint latest 7.0.0 ❯ 7.1.0 https://eslint.org
◯ now latest 17.1.1 ❯ 19.0.1 https://vercel.com
◯ typescript latest 3.9.2 ❯ 3.9.3 https://www.typescriptlang.org/
dependencies
name range from to url
◯ i18next-locize-backend latest 4.0.8 ❯ 4.0.9 https://github.com/locize/i18next-locize-backend
◯ locize-lastused latest 3.0.4 ❯ 3.0.5 https://github.com/locize/locize-lastused
◯ next latest 9.4.1 ❯ 9.4.2 https://nextjs.org
◯ rc-tooltip latest 4.0.3 ❯ 4.2.0 http://github.com/react-component/tooltip
◯ react-i18next latest 11.4.0 ❯ 11.5.0 https://github.com/i18next/react-i18next
The main advantage of upgrading your packages this way is that it's interactive.
You can go through all packages using up/down keyboard arrows, and select those you want to update by pressing the space bar.
And then, commit each change independently, and push them independently too.
This alone, will save you tons of time if any package creates a regression, because even if you don't catch the regression immediately (it may only affect part of your UI/workflow that isn't covered by any automated test).
Then you'll still have the ability to compared each deployment afterwards, and figure out when did the regression occur first, and thus know which package caused it.
Doing this will definitely save you hours of digging around compared to a easy massive upgrade of all deps at once.
To save up some time, we recommend grouping related packages upgrade together. For example, we usually upgrade all apollo-related packages at once.
Not only it reduces the amount of commits/pushes/deployments, but also it makes sense because sometimes those related package are meant to be updated together.
It's usually the case with eslint, react, typescript, etc. In the end, it's up to you to learn what feels right to group together.
If you look at the above PR, you'll notice we did some 31 commits to update 39 packages in total.
We ran into very tough bugs (crossed regression caused by 2 different packages, one of them through a
patch
version upgrade) and it would have been very hard (not to say impossible) to figure out the root cause if we had upgraded everything at once.