npm packages you should stop using and why

guide

1596829823071


npm is a package manager for Node.js that allows programmers globally to offer easily packaged open source code for sharing. You could liken it to pip for Python 2 and 3. Unlike pip, however, npm has rallied up a pretty poor reputation, mainly because packages often have way too many dependencies, leaving you with hundreds if not thousands of packages being installed per project, which makes it difficult to audit security as well as making your projects way larger (in terms of bytes) then they need to be.

And I'd like to clarify that I don't blame npm itself for any of these issues, it's moreso an issue of programmers being lazy and refusing to write their own code, even for incredibly simple tasks.

A great example of this is the infamous left-pad package. It was a simple package that would add padding to strings on the left, for example you could pad the string "hello" to be ten characters, and it would come out like this "     hello". I'm not going to go too in depth about this, and you can read more about it here, but basically the developer of left-pad got into a legal argument due to some naming conventions, and he removed his package from npm in 2016. This caused thousands of packages that depended on his package to break, all because none of those package developers would write their own incredibly simple left pad function.

In this blog post I'm going to highlight some packages that even you may use, which you should really just write yourself. The number of one-liners that get millions of downloads per week is embarrasing.

atob and btoa

Those of us who started our JavaScript career working with client-side code may have used window.atob() or window.btoa() to convert ascii text back and forth to base64 code. To our surprise, node.js does not have those functions builtin, primarily because node.js doesn't include the "window" object. So you hop on to npm and you search "atob" hoping to solve your problems the easy way. Let's take a look at the source code for atob shall we?

"use strict";

function atob(str) {
  return Buffer.from(str, 'base64').toString('binary');
}

module.exports = atob.atob = atob;

Not only is the actual logic a one-liner, it's not even complicated! Just because "atob" isn't built in, doesn't mean that Node.js doesn't have built in support for base conversion. Here's some stats:

  • Package name: atob
  • Weekly downloads: ~18,000,000
  • Dependents: 838

isarray

Admittedly, checking if a variable in JavaScript is an array isn't intuitive.

> x = [1,2,3]
[ 1, 2, 3 ]
> typeof x
'object'

The typeof operator considers objects and arrays to be the same type. However, if you did a simple google search like "javascript check if variable is array" you could have avoided installing the isarray package on npm, with this source code:

var toString = {}.toString;

module.exports = Array.isArray || function (arr) {
  return toString.call(arr) == '[object Array]';
};

Another one liner which, once again, isn't even complicated. Let's look at some stats:

  • Package name: isarray
  • Weekly downloads: ~48,000,000
  • Dependents: 458

indent-string

This one isn't a one liner, but (similarly to left-pad) it's so easy to code yourself. All it does is add tabs to the front of new lines in a string, with the option of replacing tab with a specific character. If you look at the source code, they have a bunch of error checking (which probably isn't all that necessary), and they use a slightly complex regex. This could easily be down without a regex and just a simple for loop. Stats:

  • Package name: indent-string
  • Weekly downloads: ~28,000,000
  • Dependents: 552

is-number

Once again, types in JavaScript can be kind of weird. The is-number package takes account for 4 scenarios when determining if a variable is a number.

  • The variable is just a regular number (x = 4, x = 4.2)
  • The variable is a string that is a number (x = "4", x = "4.2")
  • The variable is not infinity (x = Infinity)
  • The variable is not undefined nor null nor empty (x = undefined, x = null, x = '')

Let's take a look at the source code:

'use strict';

module.exports = function(num) {
  if (typeof num === 'number') {
    return num - num === 0;
  }
  if (typeof num === 'string' && num.trim() !== '') {
    return Number.isFinite ? Number.isFinite( num) : isFinite( num);
  }
  return false;
};

Well, it's not a one liner. If I wrote it personally it would have been, this function could be much shorter. Here's a one-liner "isNumber" function that works for all cases:

function isNumber(x) {
  return isFinite(x) && x !== null && x.toString().trim() !== '';
}

Here are some very unfortunate stats:

  • Package name: is-number
  • Weekly downloads: ~45,000,000
  • Dependents: 369

mkdirp and (probably) rimraf

These packages have a different story behind them. They are not simple one-liners that you could program yourselves, but rather are unnecessary due to recent updates to Node.js.

Node.js version 10.12.0, released in October 2018, added the {recursive: true} option to fs.mkdir and fs.mkdirSync. This likely removes the need for the mkdirp package, which was the preferred method to create recursive directories in the past.

Node.js version 12.10.0, released in September 2019, added the {recursive: true} option to fs.rmdir and fs.rmdirSync. This likely removes the need for rimraf. However, it is worth noting that as of now, the documentation for rmdir directly states "Recursive removal is experimental". It's been a year since it was added so you can probably bet that the function works as intended, but it's never wrong to be extra safe.

If you're working with an old project that requires use of an older version of Node.js, then it is perfectly acceptable to use these packages. But for any new projects or up to date projects, I'd recommend getting rid of these extra packages since they are no longer necessary.

Speed round

These packages are absolutely ridiculous. They aren't as popular as the previous ones but still get lots of downloads. I assume that some of them are made as and downloaded as a joke.

  • is-even: ~150,000 weekly downloads. Returns true if a number is even (what's a modulus?)
  • is-odd: ~700,000 weekly downloads. I think it would be too funny if someone downloaded is-even AND is-odd.
  • is-natural-number: ~2,500,000 weekly downloads. Returns true if a number is natural. So uhh, it's positive, may or may not include zero, and is a whole number that isn't infinity?

Conclusion and Takeaways

If there is anything to take away from this blog, it's that you should look into the packages you are going to download before doing so. Use Google before you use npm, the solutions to your problem may be much easier (and more interesting) than you think.