Friday Knowledge
Published in

Friday Knowledge

Better package management with npm

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

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Marcellin Nshimiyimana

Marcellin Nshimiyimana

Always debugging, because problem knowledge equals half the solution!