Better package management with npm

Marcellin Nshimiyimana
Friday Knowledge
Published in
3 min readJul 15, 2022

How can npm help you remove unmaintained packages from a big repo?

TL&DR

You can use npm i <wrapper-old-package> --global-style to prevent your teammates from accidentally importing old-package .

Photo by bert b on Unsplash

Introduction

One of many approaches to removing a package from a big project that many developers contribute to, is to

  • Keep existing functionality that rely on this package.
  • Prevent these developers from relying on the package in focus.

In this short writing, we are going to look at how npm can help us achieve these two processes.

Sample repo

We are going to use Momentjs as an example since it is popular and its maintainers discourage its usage.

We will also be using node@16 and npm@8

Below is the structure of our sample repo

root
+-- index.mjs
+-- package.json

index.mjs contains one function that calculates remaining time using Momentjs

package.json contains entry for Momentjs as a dependency.

Keep existing functionality that rely on Momentjs.

Let us do some refactoring so that our calculateRemainingTime function is moved to a workspace ( wrapper-moment), then have the root level index.mjs import this function from that workspace.

Now, our new repo should look like below.

root
+-- index.mjs
+-- package.json
+-- packages
+-- wrapper-moment
+-- index.mjs
+-- package.json

Prevent developers from relying on Momentjs.

At this point, we still have Momentjs inside the root level package.json

Let us run these two commands to move Momentjs inside the workspace’s package.json

npm uninstall moment
npm install moment --global-style --workspace=wrapper-moment

--global-style will ensure that Momentjs is only accessible inside the workspace. Therefore, importing it from the root level index.mjs should trigger an error.

We can also verify that moment is indeed now just part of the wrapper-moment package by running npm explain moment.

Moment should only be part of wrapper-moment

Why does this approach work?

Npm default installation process

npm cli implements a maximally naive deduplication algorithm, which seeks to minimize the number of duplicated packages.

It does this by generating the shortest tree possible, which in turn forces many packages to become direct children of the root level node_modules .

Node Module Resolution

Nodejs looks for the closest node_modules folder to resolve a module.

Therefore, if a package was installed because of an inner dependency, then Nodejs is going to pick it up, even if the project does not intend to rely on it directly.

Illustration

Showcasing how nodejs can unintentionally resolve modules.

--global-style will help prevent the unintended module resolution.

Conclusion

Npm has evolved into an all purpose solution that allows developers to achieve almost any package management process they want.

References

--

--

Marcellin Nshimiyimana
Friday Knowledge

Always debugging, because problem knowledge equals half the solution!