DEV Community

Discussion on: 10 useless NPM Package with millions of downloads

Collapse
 
mcmath profile image
mcmath

I’m going to go out on a limb and say that none of these are useless. Take upper-case, for example. I imagine it’s supposed to be useless because we already have toUpperCase(). But sometimes we want to do this:

let upperCaseStrings =
  lowerCaseStrings.map(upperCase);
Enter fullscreen mode Exit fullscreen mode

Whereas this won’t work:

let upperCaseStrings =
  lowerCaseStrings.map(String.prototype.toUpperCase);
Enter fullscreen mode Exit fullscreen mode

Yes, it's easy to implement yourself. In fact, I have (many times). Maybe I'll download upper-case next time instead.

Collapse
 
ghamadi profile image
Ghaleb • Edited

Yes, it's easy to implement yourself.

What's there to implement? Just use an arrow function

// typical use-case
const upperCaseStrings = lowerCaseStrings.map(s => s.toUpperCase())

// if you need it often
const upperCase = (s) => s.toUpperCase()
const upperCaseStrings = lowerCaseStrings.map(upperCase)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mcmath profile image
mcmath

But inline arrow functions are recreated every time they are evaluated. This may not be a problem in most circumstances. But in React, passing an inline function to a pure component causes it to re-render every time its parent renders; passing the same exact instance of a function may result in a significant performance boost. It may be an edge case, but it's one that I've actually encountered several times.

Yes, you can define the function somewhere else if you need it often. But then you've just reimplemented the package, proving that it does actually serve a purpose.

Thread Thread
 
totally_chase profile image
Phantz • Edited

This is a micro optimization fallacy. As every single performance analyst, and even the V8 engineers have said multiple times (there's some good talks on youtube) - don't micro optimize.

Now that we've got that out of the way, let's talk about optimization. As I just so happen to be somewhat obsessed over it too :P. Since around the mid 2010s (2015 maybe? Can't remember), V8 (the state of the art VM most javascript runs on) has inline cache. This is why higher order functions suddenly saw a massive speed boost around this time. You may remember people telling you to not use higher order functions prior to this change. There is a stack overflow thread summarising the details of the aftermath. I remember it being about different array iteration methods and their speed.

Anyway, that's the inline cache for optimizing out inline lambdas. If we want to go into nitty gritty details, the cache is actually for all expressions in Applicative Normal Form.

Anyway, this is far from being the only optimizing technique V8 has - it's supposed to make javascript ridiculously fast, so it has a state of the art JIT.

The point of all this effort from some of the greatest engineers of all time, is so that users won't care about highly superficial "optimizations" such as avoiding arrow functions.

By the way, is storing the arrow function in a variable, then using that, considered worse than pulling in an entire dependency? ;)
(this is a joke - don't actually store all your arrow functions in variables out of paranoia, for reasons mentioned above)

Thread Thread
 
mcmath profile image
mcmath

I understand all that, and I agree that you generally shouldn't worry about inlining functions. But the example I gave was pure components in React. Pure components check the properties they are passed with Object.is() every time their parent component renders. If all the properties are the same as the last render, the pure component can skip rendering, which may be a significant performance boost when rendering complex components or lists, for example. If you pass an inline function, Object.is() always fails, so you break the optimization that pure components provide. There is a React hook called useCallback() designed to circumvent this problem, but for simple cases like upperCase(), it's unnecessarily verbose.

Yes, you can easily define the function yourself, which is what I do. But if it's useful when I define it myself, then it's useful when someone else defines it in an NPM package.

Collapse
 
jyotishman profile image
Jyotishman Saikia

Hi Akim! why dont you use the css text-transform property for this? Any corner case?

Collapse
 
miketalbot profile image
Mike Talbot ⭐

Case insensitive array searching? List searching?

Thread Thread
 
jyotishman profile image
Jyotishman Saikia

toLowerCase() would work here right?

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐

Same issue as the comment above. Might need to do it for a map. I have these functions defined for that purpose. Though I agree, I wouldn't import a package for a 3 line function :)

Thread Thread
 
jyotishman profile image
Jyotishman Saikia

thats my whole point is. anyways thanks for your feedback.

Collapse
 
mcmath profile image
mcmath

CSS text-transform is a good option, but it only works in CSS. In a non-browser environment, that won't work. I'm not saying there are not often better alternatives to these packages. But all of them are useful in certain (possibly rare) circumstances.

Collapse
 
totally_chase profile image
Phantz

yeah we should probably have a package for every single prototype method since, as you said, we can't use methods in higher order functions.

Oh wait, arrow functions exist! Phew, what a relief.

Although I suppose arrow functions could be considered too much effort, so we may as well have a package for every single method anyway. Let's do that!

/s

Collapse
 
mcmath profile image
mcmath • Edited

But see my comment above about inline arrow functions being recreated every time they're evaluated. Maybe this doesn't matter in 99% of cases, but if it matters 1% of the time, then it's not useless in my book.