
You-Dont-Need-Lodash-Underscore - oceanlight223
https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore
======
vfc1
I don't understand the continuous backslash against such a useful tool like
lodash, we add 4kb and have all the utility functions that we will ever need,
what's wrong with that?

I feel that most people repeating this "you don't need lodash" meme are just
saying it because they read it somewhere, and think that bashing on lodash
makes them sound cool and looking like they know what they are talking about,
much like it happened with jQuery.

There is way too much focus on micro-optimizations like
handwriting/copy/pasting common utility functions each time to save 3.5kb in a
bundle.

It's just one more of those many examples of engineering perfectionism gone
counterproductive, which is, unfortunately, an attitude that is pervasive in
this profession and that it rarely gets called out.

~~~
chmod775
Case in point: "_.compact".

When I see stuff like

    
    
        const cleanInput = _.compact(input);
    

I have no idea what the fuck just happened. I have to open the damn
documentation of lodash (or whatever else kind of library the author chose to
use) to figure out what's going on.

Now if that was

    
    
        const cleanInput = input.filter(elem => !!elem);
    

I could've gotten on with my day and saved some time. This does not need any
documentation or comment.

This might seem like a small issue to you, but damn, I spend a lot of time
debugging random projects on GitHub, and the inability of the JavaScript
community to write readable code really trips me up every time. Instead of
just writing 2-3 lines other people can parse in a second or two, they spend 5
minutes looking up the relevant library function (which doesn't do what they
expect half the time) to produce one shitty line of code other people will
also spend 5 minutes on trying to decipher it.

~~~
irrational
>This does not need any documentation or comment.

I honestly have no more clue what const cleanInput = input.filter(elem =>
!!elem); means than const cleanInput = _.compact(input); without going to the
documentation.

What you meant to say is "This does not need any documentation or comment for
myself, because I have already memorized what all the parts of this line of
code mean, whereas I have not yet memorized what _.compact means."

~~~
marmada
There's nothing to memorize here, or there shouldn't be, because "filter" is a
standard array function in JS that I imagine most JS developers have
encountered.

Knowing how "filter" works is valuable because now you can use that knowledge
in the future on any project that uses JS, unlike "_.compact" which is only
applicable in projects that use lodash. You can be relatively confident that
you can write "filter(elem => <some function>)" and that other developers will
know what "filter" is doing.

The second part is more tricky, but still useful.

The !! operator is just two "!" operators. That's pretty normal too. The first
"!" converts an object/number/whatever into the opposite of its boolean value.
The second "!" negates the first boolean, thus turning the opposite of the
boolean value into the object's original boolean value.

Even if figuring this out on your own is slightly more difficult, it gives you
valuable insight into the language (JS is very dynamically-typed and the not
operator can cast objects to booleans), which will help you write
better/safer/more concise/clearer code in the future.

------
fluxsauce
I introduced this to our team and after a few months I have mixed feelings.
Practically, it's a micro-optimization.

Lodash is convenient, consistent, well-documented, readable, and maintainable.
Yes, there's some pretty needlessly redundant methods (isNull for example),
but it provides a nice API to do it. The trade-off of a few microseconds is
worth it.

Omitting lodash from your entire codebase is not going to magically fix all
your problems; there are much more important things you can be doing with your
time, such as delivering features or eliminating technical debt.

To reduce the amount you're requiring, you can just get a specific method like
require('lodash/omit'). If overhead is a concern, that helps mitigate it.

We have set it to warn, not to error; it's good to raise awareness that you're
doing something that has a potential performance cost, but for things like
omit the recommended native alternative just isn't worth it.

What I do find it useful for is small projects (like a lambda function) where
micro-optimizations DO count.

~~~
davnicwil
I agree with this. I think using lodash is a 'use boring stuff' decision in
javascript. It feels kind of clunky and outdated in some ways, when new native
APIs are covering more and more of what it can do year by year, but at the
same time it 'just works' in the most obvious way possible.

With native APIs, you're essentially just doing the same things with a
slightly different syntax and sure, it feels cleaner. It _is_ cleaner - where
those native APIs actually exist. But if you have to support anything but the
latest versions of evergreen browsers, now you're worrying about polyfills,
build targets, etc etc.

It's not _that_ hard, but it's just one more thing to worry about and one more
thing to be surprised by when it fails on a corner case in production.
Meanwhile, if you'd just used boring old lodash, it would be working and you
could be paying attention to something more important.

------
nemild
Am I the only one who feels that it's not a terrible thing to use Lodash? It's
relatively small gzipped (4kb for core build), a single interface for a
developer to learn, and means you don't have to think as much about the target
browser. Sure it adds a dependency, but an incremental dependency isn't often
an issue.

The .chunk is a good example (a 7 line function in native vs a 1 line function
in Lodash).

I imagine some native functions are faster, but often it doesn't matter.

I say this only partially jokingly: maybe there should be a "You don't need
javascript," and we should go back to assembly.

~~~
dubcanada
The rest it's 7 line versus 1 line is lodash uses itself. A lot of these
functions could be rewritten if other functions where there.

I do think it's silly to include 100 functions and use 2. But if we could
properly tree shake lodash there should be no problem in using lodash, you
would end up around the same as if you did it natively.

~~~
nemild
But don't we all use a small fraction of library/package and language
functionality.

\- In C's stdio, I've used a fraction of calls

\- In Ruby/Rails + gems, I use a fraction of calls

\- In Node/Express, I use a fraction of calls

\- In frontend javascript, I use a fraction of the native calls

In frontend dev, I get that this means forcing users to download a library,
but for many use cases 4 kb gzipped isn't a big deal (esp if CDNs are
involved).

I think it'd be interesting to poll developers on what part of
Lodash/Underscore causes them concern:

1\. The extra download time/bandwidth

2\. The extra costs of packaging (failed builds, extra packaging process)

3\. The speed of computation (assuming that some native functions are faster)

4\. The concern that libraries should only be used when they are highly
utilized (e.g., at least 20% of a library's code should be used before it is
appropriate to include it)

~~~
Izkata
> In frontend dev, I get that this means forcing users to download a library,
> but for many use cases 4 kb gzipped isn't a big deal (esp if CDNs are
> involved).

How about 0kb?

Whatever happened to shared-resource URLs, where there was a good chance the
library was already cached?

~~~
zdragnar
Your breaks or has minimal functionality if the CDN is down.

Your site loads slowly if the CDN is under load

Your users are now leaked to the CDN (privacy issue)

Of course, if the resource is cached, it's less of an issue, but it's still an
issue. If you don't care about those things, go ahead.

------
adregan
You don't need lodash/underscore, you need ramda[0]!

I been using ramda heavily for tasks like merging data from normalized redux
stores and it's been really handy, but it's also great for simple tasks as
well. I find the resulting utilities really easy to test and since Typescript
got much better at higher order type inference, it's become much easier to use
ramda in a Typescript project.

EDIT: The version of typescript that improved higher order type inference was
3.4[1]

0: [https://ramdajs.com/](https://ramdajs.com/) 1:
[https://devblogs.microsoft.com/typescript/announcing-
typescr...](https://devblogs.microsoft.com/typescript/announcing-
typescript-3-4/)

~~~
cj
We hired a developer for a project and they introduced Ramda into the codebade
(in addition to underscore which was already in use).

The resulting code was a mix and match of Ramda and Underscore helpers.

Flipping between Ramda and Underscore documentation the decipher the dozens of
helper / utility methods is quite infuriating.

Worse, the Ramda API was previously under _heavy_ development with breaking
changes on every upgrade. To stay up to date requires reading through pages
and pages of migration guides describing how to migrate off of one deprecated
utility method to another.

It definitely had short-term value to the person who wrote the original code
with it, but that value quickly faded.

~~~
adregan
I wouldn't recommend mixing those two libraries as they often do _very_
different things with the same name (eg. `chain` in ramda is `flatMap`) but
also because ramda mostly flips the arguments of most functions.

For example, `map` takes the function first and then the collection. That's
handy because everything is curried so you can partially apply map:

    
    
        const double = R.map(x => x * 2);
    

and can build up helper functions. Something similar in lodash would be:

    
    
        const double = (collection) => _.map(collection, x => x * 2);
    

which there is nothing wrong with, it's just that the first is more ergonomic
with `pipe` (and the potential future feature pipeline operator `|>`).

That said, it took a while to adopt at work. It wasn't until we had a critical
mass of people who enjoyed functional programming that it really took off.
Before that time, we used a few methods lightly (utils like `pathOr` and
`propOr` are so nice when you want to safely traverse an object without `o &&
o.foo && o.foo.bar`) and were very conscious that it might not be everyone's
cup of tea.

------
beart
The flip side to this argument explains exactly why I use lodash.

> You-Dont-Need-To-Write-And-Maintain-Everything-From-Scratch

I've tried writing some of the lodash functions myself to save on a dependency
and usually end up missing some edge case that was already considered years
ago by the lodash maintainers. I could have just required lodash and been done
with it.

------
bdefore
The principal thing that bothers me about lodash is here's how it usually goes
down: one piece of it snuggles itself initially and innocuously into a project
for a good use case... only _for the entire bag of tools_ to perniciously grow
into all corners. After this happens, some projects become lodash projects
instead of JavaScript projects. Those who embrace it thoroughly solve problems
differently than those who don't.

It's easy to become allergic to the API design, which subjectively I find old-
hat compared to either native implementations or Ramda. (Yes there is
lodash/fp, but there's still incongruities). And given the little variances,
within the same project you generally don't want to have lodash here, FP or
Ramda there - there is a cognitive cost. Dash way or the lo way? I accept that
not everyone finds that a problem.

More substantially problematic, if you import all of lodash and you don't
enforce an agreed upon subset of its API, you might end up having its broader
philosophies imposed upon you.

There are others, but two that really bug me:

\- I'd rather not have to grok _.chain when a codebase already has a more
idiomatic use of chaining.

\- Defensive coding is its own shed of bikes, but lodash applies it liberally,
returning an empty array instead of throwing an error when fed undefined. This
can obscure root causes, passing problems downstream and imposing an in-the-
debugger mindset. Static analysis coverage and type safety can easily fall by
the wayside.

(Linters exist to alarm you if you want to prefer native versions, or exclude
explicitly specific parts of lodash.)

------
dymk
Half the implementations that use "native" (likely polyfilled) APIs are
basically the implementation that lodash uses! Not to mention you miss out on
lodash's "chaining" API.

The suggestion is basically "don't use this well-tested, popular library,
copy/paste all this other code (with no tests) into your source tree
directly!" which is just ludicrous

~~~
thatswrong0
Yeah this is borderline insanity to me. I just don’t get the point. I feel
like the use case for this is extremely limited.. most developers don’t have
such onerous bundle size requirements that they can’t afford to include
lodash.

------
malft
The very first code snippet is a reimplementation of 'chunk' that is at
_least_ quadratic. Run away.

------
penagwin
So instead of using a highly tested, modular, versatile tool - you're
suggesting we copy-paste the functions we need?

Especially nowadays with tree-shaking and importing by module, I just don't
think it makes sense unless you only need one or two functions.

------
jtdev
Something about the way both lodash and underscore functions are
written/interfaced has always seemed incredibly obtuse and difficult to reason
about for me. FP zealotry and ideals seem to have been top if mind in
designing these libraries. I prefer the modern native functions hands down.

~~~
humblebee
This has always been my feeling towards lodash, it is heavily overloaded with
shorthand functionality that greatly reduce its readability to me.

------
SkyPuncher
To me, these articles are like arguing that your should use Assembly over C or
C over something like Ruby. Sure there are cases where lower level makes
sense, but the vast majority of modern web development has no need to be at a
low level.

I much prefer using Lodash because it's reliable and well documented. Everyone
on my team knows what it does, knows where to find the documentation, knows
where to find the examples, and knows where to find documentation of edge
cases. Lodash also includes some wonderful shortcuts and edge case handling.

Seriously, the best part of lodash isn't the code. It's how freaking easy it
is to understand and use. If you want to replace lodash, you need to look at
everything the package entails - not just the actual lines of code.

------
tlrobinson
I'm not one to prematurely optimize things, but I'd be cautious about blindly
copy/pasting some of these solutions unless you want your coworkers to make
fun of your O(n^3) set intersection algorithm:

    
    
        array.reduce(function(a, b) {
          return a.filter(function(value) {
            return b.includes(value);
          });
        }))
    

[https://github.com/you-dont-need/You-Dont-Need-Lodash-
Unders...](https://github.com/you-dont-need/You-Dont-Need-Lodash-
Underscore#_intersection)

~~~
Griffinsauce
So you stand the risk of actually learning something and improving your
skillset. I'd say that's a plus.

------
breck
Isn’t the solution just good tree shaking? Why not use something like Lodash
and just have a tree shaker in your build step filter out what you don’t need
in prod?

~~~
dymk
Not to mention Lodash has very complete browser support, unlike some of the
native solutions in the linked post

------
fortylove
Another useful aspect of lodash is familiarity. When you see a lodash function
name you're familiar with, you can instantly place that piece of code within
your mental model. No need to read 10 different implementations of the same
filter.

------
kreetx
As I understand it, this repo is also a library, but it's smaller. So, would
using something like tree shaking (i.e rollup.js) make everything unused go
away anyway (and people could continue using lodash/underscore)?

------
chovy
Nope. you don't. Don't need jQuery anymore either. Almost everything useful is
implemented in native javascript now.

