Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
No Lodash (thescottyjam.github.io)
121 points by synergy20 on March 7, 2023 | hide | past | favorite | 152 comments



I mean...sure? But this isn't very compelling when:

1. Many of these examples are just implementing the function (e.g., _.chunk). Yes, Lodash is written in Javascript, so yes, you can implement them yourself if you wanted.

2. Lodash is tree-shakeable, so if you import the functions you use directly, only those will be included in your JS bundle.

Just use Lodash, it's better than having to maintain your own hodgepodge of poorly documented and tested utility functions.


> 2. Lodash is tree-shakeable, so if you import the functions you use directly, only those will be included in your JS bundle.

I don't use Lodash, but recently began work on a project that does. I was surprised (along with the rest of the team) to find out that Lodash is not tree-shakeable by default. So if you do `import { debounce } from 'lodash';`, you're actually including the entirety of lodash in your bundle. More info here: https://lodash.com/per-method-packages

The recommended solution by the lodash team is to use `babel-plugin-lodash` (including a babel plugin to use less code? no thanks) or import the single modules directly like `import throttle from 'lodash/throttle';`. In the end, since we only used about 3 functions from lodash that were trivial to replicate, we just ditched lodash.

EDIT: There is also a `lodash-es` package with native ESM modules which may solve this issue for some. We avoided this also because it had implications with our toolchain.


For a few years I was opting to use the per-method packages from npm (`npm install lodash.pick`) but they just stopped being updated... https://www.npmjs.com/package/lodash.pick has not been updated in 7 years and is stuck at v4.4.0. I guess I missed the memo on that... and none of the npm packages have been deprecated to reflect the state of things.

Now going onto the lodash package on npm, that's listed as v4.17.21 and hasn't been published in over 2 years: https://www.npmjs.com/package/lodash

Now the lodash package on github, the latest release is listed as v4.0.0 from 2016: https://github.com/lodash/lodash/releases

There have been no commits to the main branch on github in almost 2 years: https://github.com/lodash/lodash/commits/master

I consider lodash to be deprecated at this point, and will always go for a lightweight function pulled from somewhere like SO or No Lodash.


Oh wow, I didn't realize how quiet lodash has been

Activity on master really died down mid-2017 [1]

And the most recent closed PR is jdalton this year (Jan 4 '23) saying he's not looking to expand lodash [2]

[1] https://github.com/lodash/lodash/graphs/contributors [2] https://github.com/lodash/lodash/pull/5575#issuecomment-1371...


What's more surprising is that Underscore.js[1] has seen more activity recently than Lodash (which was touted as Underscore's successor for years).

[1] https://github.com/jashkenas/underscore


Interesting! Looks like this jgonggrijp user has been keeping things moving for the last couple years: https://github.com/jashkenas/underscore/graphs/contributors


Yeah I switched a project over to lodash-es which fixed the tree shaking problem but it was painful to migrate everything


How so? You only search and replace: "from 'lodash'" => "from 'lodash-es'" and you should be good.

Unless you were importing individual functions.


Can't speak for them, but we had some CJS/ESM interop issues with our (large and overcomplicated) babel toolchain as well as with our test suite.


Yeah exactly what happened to us, it’s solvable but annoying

Also we did have a mix of things like import _ from ‘lodash’ and import foo from ‘lodash/foo’, etc


Importing single modules is so trivial and makes it tree shakeable. Is that really unacceptable?


It's not, but for 3 functions, and reducing our dependencies, it was worth just cutting lodash out. We have been happy with the change.

EDIT: And to be a bit pedantic, importing single modules is not really treeshaking. You're literally just importing and including the entirety of single modules.


> EDIT: And to be a bit pedantic, importing single modules is not really treeshaking. You're literally just importing and including the entirety of single modules.

I'd say that's basically a poor man's treeshaking because you're telling it you only want that module and its dependencies. Not it trying to figure it out for you.


The more practical scalability problem is engineers won't understand the nuance between import from lodash and 'lodash/someFunction'. You then only need one engineer to import 'lodash' and there goes your tree shaking. Front end is a mine field for junior engineers.

All of this crud builds up, and you end up with 25MB bundles and slow SPAs.


If you're that worried, why not add a CI check on the bundle size as a general smoke detector (useful for more than just lodash) and another check for plain lodash imports with a simple custom eslint rule.


Because it’s easier to just not use lodash.


I would look at making a test/checker that fails the build for such imports.

With that approach fallible humans carry less risk.


[delete]


What's being deprecated is the single module packages. So currently, you can do `npm install lodash.merge` and then just use that.

I believe the post you're replying to is referring to what I originally referred to (doing something like `const throttle = require('lodash/throttle')`, which you would install lodash normally for `npm install lodash`).


You're misreading that source. It's the separate npm packages that are deprecated, not the module imports.


Maybe a better writeup would be "the Lodash functions you don't need to bother with any more". Like _.fill, which this article correctly states can just be replaced with Array.fill these days. But e.g. _.zip still has no equivalent.

It would actually be cool if lodash started deprecating functions like _.fill (via semver so nothing breaks, of course) someday.


The problem with these utility functions is that they're not chainable. It would also be nice if they made more use of Array.map or reduce rather than using for loops and mutating things. If I couldn't do it using a simple Array.map, reduce, filter or sort, I'd still use loadash or underscore if it was loaded.


I'm curious why? It's my understanding things like for loops are used for performance reasons, which makes sense: running .map().reduce().filter() involves creating three separate arrays which can be a drag if you're dealing with a large array. For loops don't have that issue (and more broadly a utility library like lodash surely ought to prioritize performance over code readability)


Not what I meant, as one can obviously also filter or map in a reduce block, but maybe one needs to do a sort afterwards.


> one can obviously also filter or map in a reduce block

Sure but you can't filter in a map, or map in a filter.


sure. Reduce is the generic array -> anything operation, flatMap is the generic array -> array operation (and, as such, a special case of reduce), and map and filter are specialized array -> array operations (and, as such, special cases of flatMap and, transitively, of reduce.)

So you can do both map and filter as part of a reduce or flatMap, but not either as part of the other. (You may be able to get close by doing ugly things in a map/filter that abuses the second and third arguments, but I don't think you can get a general map out of filter or vice versa, and you shouldn't do the kind of things you'd need to do to get close, just use flatMap.)


You can filter in a compactMap (called just compact in lodash, apparently), FWIW. Not that this negates your point.


Reason why I like flatMap. It’s like map with a simple shortcut for filtering.


I find these fairly comprehensive writeups to be useful, because even if you would never use the more complex replacements, it makes it easy to verify that yup this is really the best you can do with pure javascript, I'll use a library for these calls.


I would think that lodash would check to see if the browser supports the methods and then use those method natively instead of a polyfil. this is the approach jquery takes


I hope lodash does not deprecate because I prefer non-instance methods personally.


> I prefer non-instance methods personally.

Why?


Semver means you'd always be welcome to use the old versions of the library if you wished.


I understand Semver, but then I'd get no new updates and for no good reason. It doesn't make any sense to remove it.


They'd be able to publish updates to older versions of the library if they so wished. Like v2.6.0 -> v3.0.0 deprecates _.fill(), then a security fix comes along so they publish

    3.0.1
    2.6.1
> It doesn't make any sense to remove it.

It does. Once the native platform supports the functionality it's redundant to keep it around and makes it less clear to a developer that the library isn't required any more. I'd argue it doesn't make any sense to use it but I'm not going to tell you that you can't. It's possible to accommodate everyone.


They'd be able to, but they won't.

I disagree. Keeping it in accommodates everyone (not just your needs). You are not forced to use it, or even bundle it. I use lodash-es w/ tree shaking as it is.


> They'd be able to, but they won't.

Why not? Until recently they were publishing individual packages for every single Lodash function. Publishing different versions that just do or do not exclude a single function is pretty simple by comparison. It seems like you want the project to hold itself back for no good reason.


Having to maintain older versions because you pulled out a function is much more burdensome than just keeping it in. I prefer the lodash way of doing things, you don't. So don't use it, that is fine.


> Having to maintain older versions because you pulled out a function is much more burdensome than just keeping it in.

Right. But we're talking about group that until recently maintained 281 separate packages. "much more burdensome" is a relative term here and publishing two versions simultaneously is absolutely not that burdensome.

> I prefer the lodash way of doing things, you don't. So don't use it, that is fine.

The solution I'm proposing lets you and me both use it exactly how we want to. I honestly find this debate to be quite baffling.


The thing is that the JavaScript version is often more readable than the lodash one (unless you have a lot of experience with lodash of course).

For example:

    _.compact(array)
vs

    array.filter(value => !!value);
Most JavaScript programmers will immediately know what `array.filter(value => !!value)` does but many will have to lookup the lodash documentation to understand what `_.compact(array)` does.


That's a good example. I looked at the first example "chunk" where the replacement is just a "chunk" function in javascript, and I asked myself what the purpose of this is, why I would copy-and-paste this chunk function rather then importing it from lodash. I think this site would be much better if it only included examples where the vanilla JS version is actually more readable.


But if you chain both of those, the `.compact()` will use Lodash iterators while the builtin will repeatedly iterate over the array.


There are 2 big categories for lodash functions:

1. Functions that have equivalently terse native versions (fill, map, etc)

2. Function that have multi-line equivalents (chunk, zip, etc)

Yes you can _.map an object and you can't myObject.map but I prefer Object.[keys/values](myObject).map(...) but for something like _.chunk I absolutely prefer to use lodash. Maybe one day we will see a new major version of lodash that deprecates all the near-native versions of functions so you can still use them but your editors will do a strikethrough and the JSDoc for the function can steer you to the native version but there are still a lot of useful lodash functions.


> Lodash is tree-shakeable... > Just use Lodash, it's better than having to maintain your own hodgepodge of poorly documented and tested utility functions.

There are good reasons not to:

- You don't want to add a build step to your project

- You don't want to introduce any additional knowledge burden on contributors to your code, other than knowing JS. Your "chunk" is the few lines of source code in your repo -- not an external thing with documentation you have to lookup.

- You don't want to deal with the security issues every dependency introduces

Let's specifically address this claim, which is often used in roll-your-own vs use-a-library debates:

> to maintain your own hodgepodge of poorly documented and tested utility functions

I feel, in this particular case, this argument is a straw man. The functions in question are basically 1-liners. The likelihood of bugs are low. The need for documentation is nil: the implementations self-document.


I don't think the idea is "if you need these 6 simple functions, use lodash, not vanilla JS". If you only need 6 simple functions, then writing them in house makes sense.

But suppose you already have usecases for lodash's more complex functions. It can make sense to use a library like lodash to fill in those functions rather than utilizing your own. And if you already have lodash available, you may as well use it for simple functions, too, rather than write your own.


> The functions in question are basically 1-liners.

No, they're not. The first one is not a one-liner. What's the point of spending the time writing your own interface, implementation, and tests of every single util that you end up needing, if you could just import lodash and move on?


The first one is 157 characters, and what it is doing can be grokked at a glance, in less than 10 seconds, by a competent developer. Choosing to format the body across 5 lines for clarity does not change that. I consider that "basically" a one-liner.

> What's the point of spending the time writing your own interface, implementation, and tests of every single util

I would not write tests for many of these, and the interfaces usually require no design because these are familiar functions like map, filter, etc, to most experienced developers.

I gave the main reasons answering your questions in my last post, and I think those reasons are powerful enough that I would consider using a lodash a mistake in most situations.

You are essentially making the "leftPad" argument, it's a kind of inverse "NIH" ethos: Why should you ever write your own anything when someone else has done it? And the answer, again, is the same: dependencies have a non-trivial cost.


I honestly haven't needed lodash in years. So much is built into JS now or very trivial to do. If I want to diff an array I don't create a diff function. I just diff it. Then there are things like fill, flatten, drop, etc, which are really just part of JS now.


TFA does not claim that you shouldn't use Lodash (the HN title is incorrect and misleading). It leaves it up to the reader to decide why they might not want to use Lodash and makes no arguments for or against such a stance.

What remains is a pretty useful overview that lets the reader see what each function is doing with emphasis on the how. It is presented as "if you wanna replace this, here's how".

If I'm not already familiar with Lodash and trying to decide whether or not to bring it in as a dependency, and see that all I need is a 1-2 liner in native JS, that's useful information. I might still conclude that Lodash is the right choice, but I think that when examined in the context of the broader industry, where 3rd party libraries are often unnecessary and sometimes actively unhelpful, I think such a page is useful.

Whether or not it's "compelling" will entirely depend on the problem you're currently trying to solve.


Introducing a supply chain vulnerability in order to import utility functions that any novice could write is a choice, I suppose. By the way, did you know it’s been seven years since left-pad?


Even if you have Lodash in your codebase, there are a bunch of functions it offers that have direct built-in analogues at this point, and I think it's still best to skip the library versions of those

Ironically I don't see all of those in this list. Maybe OP just assumes everyone already knows how not to use those


I was expecting more of a 'write your own implementation' kind of thing, but it's not really that.

For example, the replacement for _.concat() is really just advice on how to concatenate arrays in-line. In such cases, I think learning that a packaged function is not needed is pretty nifty.


This points at a larger problem: the junior developers who gleefully pull in tons of third party requirements which, as far as I can tell, is the supposed "senior" approach in javascript development.


Tree-shaking doesn't help much when the tree-shaken implementation is so bloated.

Here's the one you referenced, lodash.chunk: https://unpkg.com/lodash.chunk – 140 lines after removing comments and whitespace.

That's pretty small compared to a lot of the lodash utilities. Try spot-checking a few on unpkg.

I prefer angus's `just` utilities: https://github.com/angus-c/just


Do you have any examples that show that `just` is more efficient than lodash? It doesn't even have a `chunk` implementation, so it's hard to say that it's better.

The "bloat" is the result of being battle tested. A slimmer implementation would cut out edge cases that I may or may not run into. If I use Lodash, I know I'm all set.


> The "bloat" is the result of being battle tested.

Not always. Lodash's _.find is 5k. Why is something as simple as find so huge? It has a lot of magic. A lot of that magic provides safety though.

I don't recommend dropping lodash unless you can start using typescript.


The point of the OP is that you don't need dedicated functions for most of these utilities, let alone hundreds of lines of code.

0 lines of code is preferable to battle-tested code.

10 lines of code is preferable to 1000 if you don't need them.


The point of the OP was that _.chunk is 140 lines, which is apparently too much. But `just` doesn't even support chunk(), so it's unclear what the advantage is. Sure, you can theoretically spend your time crafting your own implementation, but why? For the self-satisfaction? I'd rather just get on with my work.


I would probably just copy the implementation from lodash or stackoverflow and fix it up.


A chunk replacement is only 6 lines according to:

https://youmightnotneed.com/lodash#chunk


If you are using code splitting then importing directly gains you nothing.


Would be nice to have some indication of the size of the replacement visible before I click, so we can scan down the page and get a sense of what is what.

That is, I'd love to see how many of the replacements look like

    _.now()   ->   Date.now()
and how many of them are like

    _.invert(object) -> 

    function invert(obj) {
      const newObj = {};
      for (const [key, value] of Object.entries(obj)) {
        newObj[value] = key;
      }
      return newObj;
    }
Also clicking through I see a lot of "when lodash was created this was necessary because X, but now we can Y". Kudos for including that. It is both informative and helps this not come off as an attack.


Yes -- this seems like it would be significantly more useful if it divided between "vanilla Javascript now supports this or similar functionality natively" vs. "if you're getting rid of lodash and use these functions, then you'll have to write your own variant, along with tests".


> Also clicking through I see a lot of "when lodash was created this was necessary because X, but now we can Y". Kudos for including that. It is both informative and helps this not come off as an attack.

It reminds me of https://youmightnotneedjquery.com/ in a good way.



Lodash gets so many things wrong I’d rather not see it in most projects. I appreciate a good utility library for JS projects but my go-to choice has to be Ramda[1]. Every function it exports is curried and works great with pipe which enables me to write highly reusable and composable functions in pointfree notation. I have never been as productive with lodash, and I find the functional style easier to read

[1] https://ramdajs.com/


if you enjoy functional programming and are looking for a utility library, ramda has been a joy. very very well thought out. being able to compose functions together and treat data as a stream of information being transformed is incredibly easy. it is also compatible with libraries which implement algebraic structures like fantasy land. coupled with the other r libs its quite fun to program with. just be careful as it gets hairy to read pretty fast if one doesn't understand all the functions that come into play...

  // pull traits dictionary out of tokens
  const extractTraits = R.pipe(
    R.map(R.pipe(
      R.last,
      R.prop('attributes'))),
    R.reject(R.isNil),
    R.reduce(R.mergeWith(concatValues), {}),
    R.map(R.pipe(
      R.unless(R.is(Array), R.of),
      R.groupBy(R.identity),
      R.map(R.count(R.identity)),
      R.toPairs,
      R.sortBy(R.prop(0)),
      R.map(R.zipObj(['name', 'count'])))));


Cannot recommend Ramda enough. It's a great utility belt to build your application with. Only downside is the pushback I always receive from the team when I try to introduce it.


Reading the insightful comments in this post, I see why accommodating JavaScript's inherent flaws has snowballed web development. You need to know concepts like tree-shaking (removal of dead code) to pick among 10 different libraries that mostly do the same in subtly different ways.


I've similarly enjoyed Remeda for first-class Typescript support, though I don't know it intimately and it is a much smaller project.


What does it get wrong


How does it compare with fp-ts?


What is "pipe"? Surely you're not referring to the bitwise-or operator `|`?


Ramda has a composition (left to right) function named pipe: https://ramdajs.com/docs/#pipe

It's similar to the pipe operator seen in other languages (Elixir, F#, etc). There is a proposal to add a pipe operator to JS as well - still in early stages, though.


It’s for connecting functions together like a pipeline, the same as compose but the fn list is reversed. Lodash has something similar called chain, but that’s harder to extend and isn’t as portable as partially applied functions


Libraries like lodash/underscore don't get popular for no reason. The API matters, and readability matters. Sure, you can do these things without the library, but the readability suffers. Adding in the ability to chain these calls into a nice little readable "paragraph" of small single step data changing functions, there's significant value in the underscore and similar compatible libraries.


I am sure you are right. However, this does look very useful to me.

I am not a professional js developer but I do like to build dinky websites. I generally prefer not to bother with build steps or dependencies. For me it's preferable to have my own implementation of a function within the file or project I am working in. That way I can directly inspect what the function is doing, which is "more readable" to me.

Moreover, sometimes I need functionality that is similar but just a bit different from something that lodash does. This seems like a good resource to check for inspiration.


> The API matters, and readability matters.

Exactly, lodash should be part of the language. https://github.com/mlajtos/es1995


Lodash also handles "bad-types" in really graceful ways. In fact, it's almost the primary reason I use it.

For example, if you have a nullable array. In plain JS, you have to check the presences of the array, then run `find` (or whatever function). Lodash simply treats it like an empty array - returning nothing.

This is particularly handy in React where it creates clutter to have to check for the empty state.


In your nullable array example, you could just use optional chaining. There’s no need for lodash.

I personally feel this type of ultra-defensive programming where all types are assumed bad only harms you long run, adding complexity where it isn’t necessary to solve problems that don’t exist, and swallowing errors making it harder to debug. Exceptions exist for a reason.

When I switched to TS it was a great incentive to ditch lodash because it was munging all my types. This in turn simplified my code as it made me aware of unnecessary guards, coercions, and errors that lodash was swallowing.


Having worked in the JS ecosystem for far too long now it's enormously satisfying to remove these dependencies. First it was direct DOM manipulation without jQuery getting in the way, now it's direct JS calls without a utility library getting in the way. The ecosystem really has come a long way.

It's also worth noting that lodash lets you import individual functions, e.g.

import throttle from 'lodash/throttle'

so even when you do need a utility function you can avoid pulling the entire library into your code.


Looks like this will be removed in v5. "For example, throttle uses debounce internally. In a project using both methods from the main lodash package, throttle will import the same debounce module as any code that imports debounce directly, so only one copy of debounce will wind up in a webpack bundle."


Looks like the v5 deprecation is only the separate modules.

"lodash/throttle" loads throttle.js in the lodash package.

"lodash.throttle" loads index.js in the lodash.throttle package.

The latter is being deprecated but not the former.


> Having worked in the JS ecosystem for far too long now it's enormously satisfying to remove these dependencies.

Assuming you're working on commercial products, how do you decide when to move to new-ish native functions? For example, do you log feature detection for the function a month or two prior to the planned change?


You probably have HTTP access logs and can use that to run your own calculations based on UserAgent and caniuse. We are in enterprise, and 90% of our users are on evergreen browsers, and the next 9% have a browser version from the last 18 months. For the last minority, we conditionally include a polyfill from polyfill.io

“Browser support” is not an issue anymore unless you do something cutting edge, sell to regulated industries like healthcare, or serve many users in China/Africa et al.


There’s an entire category of developer that concerns themselves with stuff like this, and I wonder if they know you can be a successful dev and not care one bit about taking your imports this seriously, and instead just grabbing libraries from npm.

It strikes me as the difference between knowing why your role exists and not realizing you deliver organizational value, over engineering perfection.


An important role of developers is knowing which tools exist and what can be used to provide value.

To use Lodash, a developer needs to know what is available there in the first place. You're taking it for granted, but everyone, you included, had to study its documentation and memorize which functions were there, even if it was only to "look it up" later.

Someone like you could have said a few years ago about Lodash: "why do I need this stupid library, I will just use for loops everywhere, like I learned in college. They get the job done and my role is to provide value, not to care about libraries or code reusability".

With this website, it's the same thing: it's there to teach you which things in Lodash aren't needed anymore and which are. Then it is up to the developer to use what's best. Not everything in the internet is prescriptive.

Blind dogmatism shouldn't have a place in our profession.


That's kind of my point, though? Caring about "blind dogmatism", one way or another, is not required to be a highly effective software dev.

For example with lodash, the process for deciding to use it could be, "Hey this looks like it could save me time, let's try it." That's it. You don't have to go on this large, multi-hour/multi-day journey discovering every little thing about it first.

I'm arguing here that highly effective developers are able to use software to solve business problems favoring efficiency over correctness.

And I'm not sure it's efficient to care much about whether or not lodash could be rebuilt internally.


You say "one way or another". What is the "another" way, and who's advocating it? This page is NOT an invitation to rebuild lodash on every single project. It is not a prescriptive website. It is teaching material.

This page is here, for example, so that people who only know about Lodash can know how it's implemented. If they ever start working on a no-Lodash project, they might not need to import Lodash.

This is not a call-to-arms to uninstall Lodash from all projects and replace with hundreds of functions. Why would it be?


Then this page could be replaced by looking at lodash's source code. In fact this page is harmful as it does not represent, precisely, what lodash is actually doing and should not be used to understand lodash.

Further, I'm not responding to the page itself, but the discussion here around the page. A lot of developers are using their emotions (e.g. disgust, fear) to navigate their professional role, and I'm suggesting that this need not be the case.

You can set all of that aside and be a highly effective developer. You don't need to care about any of this, and I'm seeing a lot of devs here who think they have to care in order to be effective.


It couldn't be replaced by looking at Lodash's source code, because A LOT of the alternatives here are built into Javascript, and the Lodash code is significantly larger.

Check flatten in this website:

    array.flat();
Versus Lodash:

    function baseFlatten(array, depth, predicate, isStrict, result) {
      predicate || (predicate = isFlattenable)
      result || (result = [])

      if (array == null) {
        return result
      }

      for (const value of array) {
        if (depth > 0 && predicate(value)) {
          if (depth > 1) {
            // Recursively flatten arrays (susceptible to call stack limits).
            baseFlatten(value, depth - 1, predicate, isStrict, result)
          } else {
            result.push(...value)
          }
        } else if (!isStrict) {
          result[result.length] = value
        }
      }
      return result
    }
About your point: sure, nobody has to care about all of this. But I don't see why we should give people a hard time because they do on their free time.


Exactly; lodash doesn't use `array.flat()`, so the site does not teach, "how it's implemented."

And I'm not giving people a hard time, I'm saying you don't have to care about all of this to be good at your developer job. If this was an obvious point to you, great!


The point of this website is not to show how Lodash implements things. Why would it be?

It says so in there: it is "a description of how one would go about doing the same thing in vanilla JavaScript".


You're arguing with yourself now, as I just quoted you:

> This page is here, for example, so that people who only know about Lodash can know how it's implemented.


I said "for example".


Yes, and I responded to that example. Not sure what the problem is. Do you not think it's a good example?


To be more precise, my point was more that this website shows how it is implemented in general. There is still something to be gained by showing that you can do array.flat() instead of just copy pasting from Lodash.


Yes, for sure, I didn't mean to imply the website is entirely worthless, sorry.

But my larger point here is just that you don't have to care about "only importing lodash if absolutely necessary" to be a good dev. You can care about those things, but for the folks who think they have to care, I'm here to say you don't.


It's not that hard to do a basic cost benefit analysis of adding a package before you throw it in your package manifest. It usually takes minutes, not hours (and certainly not days). Skipping this step doesn't gain you major efficiencies and definitely doesn't make you a better developer.


If you're unsure why this must be said, you've never worked in a large corporate environment. People will spend weeks on decisions like this.


However, going into such multi hour/day journey once in a while is very effective way to learn. And writing down that journey is also very effective in forcing you to really go through and really learn.


Speed brings value. Loading dash without optimizing it carries a huge weight. Weight can slow down users. Users leave the cart before completing a purchase.

Lodash is engineered to deliver “perfection” and performance, to an absolute fault. Try `import {unary} from 'lodash'` and tell me how big the bundle gets. FYI unary should be `fn => x => fn(x)`.

On the other hand, copy-pasting actually-useful utilities like groupBy from some random site defeats the purpose of npm. Luckily there are sane Lodash alternatives like Just:

https://github.com/angus-c/just


> Loading dash without optimizing it carries a huge weight.

This doesn't pass the smell test for me, considering how small the library as a whole is, and the many, many use cases that would not involve exposing the code to the user at all.



Per your citation, at 875 kB/s it takes 28ms to download. I'm gonna leave that in the "small" category for now, considering 516.25 kB/s is about what Cuba averages on mobile, ranked last in the world. [0]

[0] https://www.speedtest.net/global-index


28ms isn't small trade-off if you're pulling it in for a one off utility function. Not calculating these types of trade-offs is exactly how you run into mammoth bundle sizes when you're a year or more into development.


28ms is a small trade off. Sorry, but it is, and this is exactly my point; you don't have to give a hoot about 28ms and you can still be a very effective developer.

In fact, I find it hard to think of an effective software dev who does care about 28ms without having specific reason to, due to a niche use case (not a generic web app for Internet things, like a hospital instrument that needs every ms).


..and when you've added a couple dozen of these you're sitting at half a second.

Indeed, I guess we just develop different classes of applications. I don't know what a "generic web app for Internet things" is.


Who here is suggesting you add a "couple dozen" of dependencies like this?

And you're on a "generic web app for Internet things". This page loading 27ms slower would not be perceptible.


If you're not evaluating every package you're adding to your manifest how would you prevent that scenario from happening?

Personally I've never worked at a product where response time wasn't an important metric.


Hm, so you think it's better to calculate response time than to measure it as a way of tracking this important metric?


Why would those things be mutually exclusive?


Which, of the two, would be more accurate and relevant to users? Do users care about an estimated 27ms increment that they objectively cannot notice, or the overall measured response time?


Considering that a bigger engineering and social problem in the Javascript world is the plague of micromodules of dubious provenance, arguing against using solid and trustworthy utility libraries is counterproductive, or even symptomatic.

Using libraries like lodash, instead of adding 12 left-pads of different authors to the dependencies manifest, is an improvement over the status quo.


You can be a successful dev without doing a good job. Many people just want to do a good job and don't particularly care about being "successful."

It's not that your coworkers don't know you can get away with doing a bad job, it's that they're not motivated by the same things that you are.

It's true that in some contexts, throwing npm libraries at the wall to see what sticks is delivering organizational value. In many others, it's negative value.


That's the point; there is no "successful dev" without "doing a good job".

The folks who don't care about being "successful" are not "good devs", because they're not clear about why their job exists in the first place. You don't really get to define success for your role without your organization's input, and when you overly focus on the engineering to the exclusion of delivering value, you are not acting as a "good dev".


Hitting metrics or whatever else causes you to be successful in your organization is not the same as doing a good job. It is possible, for example, to get raises and promotions while ruining your company and destroying all value for your customers. It is also possible to be the only one delivering any value, while actively working against organizational goals. Management, or whoever else is defining success for you, is not infallible.

Intrinsic motivation is a real thing. You don't have to let your boss or your parents or your teachers tell you what it means to do a good job. You can decide for yourself.

People who just grab libraries from npm and don't take their imports seriously are not the ones delivering value in the places where I've worked. Far from it. Those are the people whose "work" you have to re-do weeks or months later because it didn't actually deliver value. Often times it doesn't work at all, never worked, never compiled, etc. But those people are long gone because they're busy being "successful" and moving on to other roles, creating negative value in other parts of the organization.

You say that only successful people know why their job exists, and unsuccessful people are blind to organizational value. In my experience, you couldn't be more wrong.


Go one step further; what are the metrics trying to measure? Who set those metrics and why? What are the smallest number of actions needed to deliver value to the folks who provide revenue to the company?

Effective developers know the answers to those questions. What else they do is quite varied, and some effective developers care about things like "should we use lodash or not?" But other effective developers don't.

I didn't say "only successful people" do anything. What I said was you don't have to care about how lodash works or be concerned about importing it vs. rolling your own to be an effective developer.


this attitude is how you get average client payload size measured in the tens of megabytes


Missed a golden opportunity to call this Nodash.


I would have gone with em dash, since lodash was a successor to underscore, so this would bring it back in a typographic direction.


That would be Nonederscore


I don't think I could bring myself to say that out loud.


I’d still use Lodash functions over the native ones for chaining [1].

I like Elixir pipelines so this is equivalent. I suppose it depends on preference if someone chain or not.

[1]: https://docs-lodash.com/v4/chain/


To be fair a lot of these utility functions are easy to implement without the dependency.

And one can install only the individual lodash functionality that’s required. Personally I’d do this in the node/js ecosystem because everyone does it and why not? It’s battle tested.

I work primarily in Go so I’m used to writing my own utilities for many things. It isn’t that complicated and end of the day it’s just basic programming.


> Personally I’d do this in the node/js ecosystem because everyone does it and why not? It’s battle tested.

When almost all software is completely terrible, "everyone does it" is not a compelling reason to do anything. And this approach is indeed battle tested, in battles that were abject massacres (see left-pad).


Well, I just dont think that "almost all software is completely terrible" is true. In particular, many libraries are actually good or at least better then own half-baked solutions you never had time to test thoroughly.


lodash and other utility libraries can be helpful when backend devs who don't usually work in JS need to do something complicated on the front end.

That said, if focusing on front end dev work I think it removes knowledge of underlying apis which can be counterproductive in the long run. If you have enough knowledge to achieve in plain JS what is done with lodash, you are better set up for success when given a problem not yet solved in your code base or stackoverflow.


This is true for backend frameworks too. In the PHP world, Laravel contains many helper functions that uselessly duplicate functionality already available in the standard library. Not only is this a waste of effort from the framework's author, it also unhelpfully silos some developers into Laravel-specific knowledge. I had a colleague who had worked professionally as a Laravel developer for several years but then failed a job interview because he'd literally never written a vanilla PHP script and had no idea how to go about it.


The title needs an update. The current title is actively misleading and is affecting the comments.

The content does not claim that you should not use Lodash. It only presents alternatives to Lodash functions. The actual title "Lodash Replacements" is far more accurate by reflecting what the page contains, and doesn't invite misinterpretations or ideological responses.


Am I misreading or are there no translations to pure JS available specifically for collections? The ease of being able to do "what i think I want to do in my head" with a collection using a one-liner often is the primary reason I'd use anything Lodash-y in the first place. The fact that I can import those methods directly to my projects and forget about the guilt of bundling the rest of the library really have kept Lodash top of mind for me for years.

I have found that not so much when writing my own projects and tinkering, but specifically for "real" work (at my job) is when I have to deal with iterating over collections all the time. Anything less readable than Lodash is just overly annoying thanks to JS verbosity. Most people wouldn't remember to pull these methods out of a utils directory that we maintain simply for the purpose of ignoring packages like Lodash.

By a collection, I'm talking about an array of objects that follow the same pattern.


https://github.com/you-dont-need/You-Dont-Need-Lodash-Unders... seems to be a more readable alternative to this website.


I agree, the days of chaining lodash functions together are pretty much behind us.

But I still like lodash, particularly for functions like these:

- words

- kebabCase / startCase / snakeCase

- partition

- debounce

Basically the more advanced functions for which no readily available alternative exists?


> You need to enable JavaScript to run this app.

What app? Is this an app? If it is, why didn’t you name it or tell me what I’m missing out on instead of using the default some framework spits out.

[temporarily enables JS for the site]

Oh, it’s just static informational content that should have good SEO and TUI-compatibilty but missed the mark. Don’t need Lodash? How about this page doesn’t need JavaScript! These code examples are the perfect semantic use case for the <details> + <summary> elements.

(And I love JavaScript, but for contexts that need it like applications)


If someone on my team imports Lodash and uses it all over the place to significantly reduce our LoC, fine by me. What makes it annoying is when someone adds that whole dep just to use it once, or for something ES6 already has (e.g. map). Same with Axios instead of fetch.


It is really annoying (and in my opinion, almost misleading) that named imports from lodash do not tree shake. That said, you still can import individual modules without having to use the entire library. At my company we had to turn on linting rules to make sure our developers do not continue to import the entire library. Or even worse, import '_'


Didn't see anyone mentioning Lodash's IMO biggest flaw: being null/undefined safe. As in `_.map(undefined, (item) => item)` returning an empty array. Promotes sloppy code and interfaces really badly with TypeScript.


Fun exercise, use cgpt or copilot to convert the descriptions into code and then roll your own then check correctness and benchmark cgpt, your own, author's own and lodash.


I never understood the conviction behind these silly purist initiatives lol, especially on the job, in the real world.


Why do you assume this is a "purist initiative", rather than what it says it is on the tin ("a catalog" of alternative implementations)?


I think it is unclear why you would write a list of alternatives to lodash unless you are trying to make the case that using these implementations is better than using the lodash functions. There is also a pretty long history of "you don't need to use lodash" articles and sites arguing that lodash is a crutch or simply bad.


It's not really unclear. It is for people to learn more things, update their knowledge and use the library piecemeal if necessary. It is always up to the person learning to make a decision on what to do afterwards.


The back button doesn't work on function detail pages. (Using Firefox 110 on Android.)


maybe a dumb question but isn't lodash already implemented entirely in vanilla js? wouldn't the equivalent be just looking at the lodash source code?


1. By "already implemented entirely in vanilla js" you mean that there are native functions for everything?

If so, no, it's not entirely useless. Check the article for examples where it isn't.

2. No, for most things there are several differences between what is on Lodash source code and the current native-Javascript implementation. Check this: https://news.ycombinator.com/item?id=35057549


What does this provide that https://youmightnotneed.com/lodash/ doesn't?


Where is .cloneDeep? That alone is mainly what I use lodash for.

Even though JS is pass by value, if you pass an object, the other nested objects will still be references to its predecessor.


We used `cloneDeep` heavily at a previous role, it isn't particulary fast - so be careful if you cloning very big objects (1mb+). There are faster options out there such as https://github.com/davidmarkclements/rfdc or even https://developer.mozilla.org/en-US/docs/Web/API/structuredC...


I like `fast-copy`. Never had an issue with that.


Technically it's called call-by-sharing.


Why? Lodash evolved to quite stable status with predictable results.


lodash is great because you can import @types/lodash into your TS project and have great inferred types from things like _.uniqBy or _.omitBy; without such support, vanilla JS "equivalents" are just not useful




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: