To understand why this is an interesting decision to make in the first place, we need to have a look at the history of package management in javascript.

Pre npm : frontend dependencies are downloaded manually and stored into the repositories 📁

: frontend dependencies are downloaded manually and stored into the repositories 📁 2010 : npm is released and supports nodejs 📦

: is released and supports 📦 2012 : npm usage is dramatically increasing - primarily due to Browserifys browser support 🎉

: usage is dramatically increasing - primarily due to browser support 🎉 2012 : npm get a competitor, bower , that entirely supports browsers 💻

: get a competitor, , that entirely supports browsers 💻 2012-2016 : The number of dependencies for frontend projects increases exponentially 🤯

: The number of dependencies for frontend projects increases exponentially 🤯 2012-2016 : Building and installing frontend applications becomes slower and slower 🐢

: Building and installing frontend applications becomes slower and slower 🐢 2012-2016 : An infinite amount of (duplicated) dependencies are stored in nested folders within the magic node_modules ☢️

: An infinite amount of (duplicated) dependencies are stored in nested folders within the magic ☢️ 2012-2016 : rm -rf node_modules the most frequently used command as a frontend developer..? 🗑

: the most frequently used command as a frontend developer..? 🗑 2015 : bower lose the battle against npm 💀

: lose the battle against 💀 2015 : node_modules are changed to a (more) flatten file structure! 🕸

: are changed to a (more) flatten file structure! 🕸 2016 : left-pad becomes the worldwide news of the day 👈

: becomes the worldwide news of the day 👈 2016 : yarn is released 🚀 Supports both npm and bower repositories yarn.lock locks installed versions and provide deterministic dependencies. No more rm -rf node_modules ! yarn install spend about half the time versus npm install (without using cache) Caching and offline mode enables build processes to consume nearly no time

2016 : npm releases shrinkwrap 🧯 An attempt to handle dependency locking Unfortunately, several errors and promising more than it could manage - the reputation of the tool became poor

2017 : npm 5 is released 🔓 package-lock.json is their new tool, shrinkwrap is put aside package-lock.json take on the fight against yarns lock file

2018 : npm ci is released 🛬 Build code using package-lock.json directly No expensive security and version analyses on the dependencies Build time is drastically reduced on the build server!

2018 : npm 6 is released 👮‍♀️ npm check security vulnerabilities for dependencies to be installed No significant variance in build time between yarn and npm

2019 : tink is in beta mode 🦋 Avoid using node_modules and rather have one file with hashes for each dependency in the project Not yet production-ready

...

Phew 🥵

As we can see, after the release of yarn , npm has been inspired (and forced?) to develop lots of good tools and mechanisms. yarn should get credit for addressing some important problems related to npm and put pressure on their competitor back in 2016. Both speed, security and deterministic package handling are essential features that allow today's developers to focus and concentrate on creating value - and not fighting the tool.

Conclusion 🤔

For convenience, I would recommend most teams (who have to make numerous other and more important technologically decisions) to choose the easiest option - npm . It is shipped with node and is, in 2019, sufficient enough to handle package management in a good manner.

Always an exception? 🧐

When using monorepo, yarn workspaces is a popular alternative whereas npm doesn't offer an equivalent alternative. lerna is a package that also supports usage of monorepos and works with both npm and yarn (with workspaces )

pnpm 🥉