DEV Community

Cover image for How I brought down my project's dependency tree from 36 packages to 4 packages
Saurabh Daware 🌻
Saurabh Daware 🌻

Posted on • Updated on

How I brought down my project's dependency tree from 36 packages to 4 packages

Before you npm install package or <script src="https://coolframework.com/file.js"> do you ever ask yourself if you really need this package/framework/library?

Is there any way I can implement the same thing with my own functions?

If the package has 300 functions and I need 2 functions then is it really worth having it in my dependencies?

I did not ask these questions to myself when I started with my project called ProjectMan and installed 3 packages Commander.js, Inquirer.js, and Chalk.

But that ended up putting 36 packages in my dependency tree! So npm install -g projectman was installing 37 packages. What if any one of these packages break down? Do I really need to make people install 36 packages to run my simple command-line tool? More packages = More time to npm install and what if anyone cancels the install?

So after v1.2.0, I decided that I would minimize this size as much possible for v1.3.0 of ProjectMan and started replacing my dependencies one by one.

Target 1 :: Chalk

It is a library to color text on the console.

It has 6 dependencies (including direct and indirect dependencies)

But I didn't really want rainbows flowing through the console of my users 🌈 I just wanted few colors.. so I simply checked what chalk.bold.red("HelloWorld") returns and it returned this horrible looking string:

`\u001b[1m\u001b[31mHelloWorld\u001b[39m\u001b[22m`

As you can see there's HelloWorld inside this string I tried replacing it with other text and it still worked. I did the same thing with all the colors I was using and simply created a colors.js file in my project that now looks something like

// Just some weird strings that color text inside it. You probably will not have to touch this file.

exports.green = (message) => `\u001b[32m${message}\u001b[39m`;    

exports.boldGreen = (message) => `\u001b[1m\u001b[32m${message}\u001b[39m\u001b[22m`;

exports.boldRed = (message) => `\u001b[1m\u001b[31m${message}\u001b[39m\u001b[22m`;

exports.yellow = (message) => `\u001b[33m${message}\u001b[39m`;

exports.boldYellow = (message) => `\u001b[1m\u001b[33m${message}\u001b[39m\u001b[22m`;

exports.grey = (message) => `\u001b[90m${message}\u001b[39m`;

exports.boldGrey = (message) => `\u001b[1m\u001b[90m${message}\u001b[39m\u001b[22m`;

exports.bold = (message) => `\u001b[1m${message}\u001b[22m`;

These 17 lines (including line breaks and comments) replaced 7 packages!!!

And Boom my package was down to 30 dependencies.

Here are changes that I made in repository to achieve this:
https://github.com/saurabhdaware/projectman/commit/413355b41d87ff18c9dcf02bebf51d3da35372b3

Target 2 :: Inquirer.js

Inquirer provides beautiful interfaces for taking input in the form of lists, text and so many other options.

I personally loved this library but the only thing that was bothering me was the dependencies it came up with. Inquirer is dependent on 28 packages (including direct and indirect dependencies). Even for the features inquirer provided, 28 packages were too much!

There was no way I could implement it with my own functions since it has way too many features and it was not possible for me to code all these features.

So I started looking around for alternatives and found prompts.

Prompts can do almost everything that inquirer can and has dependencies of 3 packages (including direct and indirect)!! Although I felt like some of the functions of prompts are not as stable as inquirer but for my case, it worked after some minor workarounds.

And Boom 4 packages replaced 29 packages! ProjectMan was down to 5 packages!!!

Commander.js

Commander is an amazing library and has 0 dependencies so I still use it and I totally love it!

Conclusion

My package runs exactly the same on 4 dependencies as it did on 36 dependencies and did not cost me any scalability issue or bug or breakdown of any major feature.

Before you install a script/package/framework just wait a minute and ask yourself these three questions

  • Do I really need this library?
  • What functions do I need? Is there any way I can write my own function without putting a lot of time and without costing scalability or other issues?
  • If I can't write own function then is there any other stable alternative package that uses lesser dependencies and does not break anything from your package?

Also,

I am not against any of these libraries, There are particular cases where you may actually need a lot of functionality from these libraries and you should totally use them in that case.

Thank you for reading! Do comment and let me know your thoughts about this :D

Twitter: @saurabhcodes
Github: @saurabhdaware
ProjectMan Repo: /saurabhdaware/projectman

Top comments (16)

Collapse
 
tyrrrz profile image
Oleksii Holub

Just make sure to cover all of your handwritten functionality with tests now

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

yes working on it :D thanks for reading 🌻

Collapse
 
johanalkstal profile image
Johan AlkstΓ₯l

This is the right kind of thinking. Thumbs up.

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

Thank you :)

Collapse
 
jamesthomson profile image
James Thomson

I'll always have a look through a packages dependencies list before considering adding it to a project.

A tool that's helpful when doing this: bundlephobia.com

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

Oh I didn't know about bundlephobia thank you for sharing

Collapse
 
pavelloz profile image
PaweΕ‚ Kowalski

Good investigation and solution from your part.

Its so refreshing to see someone caring about how much junk they ship with the app.

I hope more people will take care about it.

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

Thank you so much🌻🌻 and yes every developer should spend some time deciding what frameworks or libraries are actually needed :D

Collapse
 
zaidrehman profile image
Zaid Rehman • Edited

I used almost a similar approach to remove lodash completely from my project πŸ˜…πŸ˜…

Personally I feel it's a right approach.

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

Do you have a link to this commit or PR? Would love to see how you did :D

Collapse
 
zaidrehman profile image
Zaid Rehman

Sorry bro it was a private repo of my employer.

Thread Thread
 
saurabhdaware profile image
Saurabh Daware 🌻

oh ok no problem. good job though :D

Collapse
 
azeem2793 profile image
Agha Azeem

πŸ‘ that’s brilliant

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

thank you so much :D

Collapse
 
syntaxseed profile image
SyntaxSeed (Sherri W)

I do the same with my PHP dependencies. I give preference to packages without a ton of sub dependencies.

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

Yes I feel this is right approach and applies to any domain and any language and even on the frontend