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)
Just make sure to cover all of your handwritten functionality with tests now
yes working on it :D thanks for reading ๐ป
This is the right kind of thinking. Thumbs up.
Thank you :)
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
Oh I didn't know about bundlephobia thank you for sharing
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.
Thank you so much๐ป๐ป and yes every developer should spend some time deciding what frameworks or libraries are actually needed :D
I used almost a similar approach to remove lodash completely from my project ๐ ๐
Personally I feel it's a right approach.
Do you have a link to this commit or PR? Would love to see how you did :D
Sorry bro it was a private repo of my employer.
oh ok no problem. good job though :D
๐ thatโs brilliant
thank you so much :D
I do the same with my PHP dependencies. I give preference to packages without a ton of sub dependencies.
Yes I feel this is right approach and applies to any domain and any language and even on the frontend