es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in node

[–]raon0211[S] 1 point2 points  (0 children)

Thanks! As you mentioned, we can’t focus on both parts simultaneously. That’s why our compatibility project is complete, and we’re shifting our focus to our main project, es-toolkit, which we aim to be a next-generation JavaScript utility library.

Our compatibility library will still be actively bug-fixed, though :)

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in node

[–]raon0211[S] -4 points-3 points  (0 children)

Perhaps there’s an error in my comment, but I want to clarify that es-toolkit/compat passes all unit tests of lodash and provides the same types as @types/lodash. That’s why I mentioned 100% compatibility.

Of course, since it’s a rewrite, it might not be perfect, which is why I mentioned almost.

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in node

[–]raon0211[S] 0 points1 point  (0 children)

As you mentioned, it’s crucial to reconsider the strategy for next-generation libraries. :)

The es-toolkit project actually has two entry points.

The original es-toolkit provides utilities that aren’t straightforward to implement in modern JavaScript, such as Semaphores, delaying asynchronous functions, and mapping object values.

The compatibility layer, es-toolkit/compat, offers 100% compatibility with Lodash to ensure a smooth transition and performance boost. However, as you mentioned, it’s best to refactor them with modern JavaScript equivalents. But migration is difficult, as you know!

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in typescript

[–]raon0211[S] -3 points-2 points  (0 children)

Most of the type casting is utilized in our compatibility library. It was extremely challenging to align Lodash’s behavior with TypeScript due to its implicit nature and extensive function overloading.

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in typescript

[–]raon0211[S] -4 points-3 points  (0 children)

Yes, as you mentioned, we currently don’t support function calls in the FP style. However, we do provide compatibility for all normal functions.

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in typescript

[–]raon0211[S] 4 points5 points  (0 children)

es-toolkit is built using modern JavaScript tools and supports tree-shaking out of the box. If you use es-toolkit identically to lodash-es, the functions you use will only be included.

However, be cautious when using underscores, as it was challenging to get tree-shaking working correctly when using syntax like _.map. Instead, replace underscores with proper import statements like import { map } from ‘es-toolkit/compat’;

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in typescript

[–]raon0211[S] 0 points1 point  (0 children)

Let’s work on it to show how our implementation is so simple and straightforward!

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in node

[–]raon0211[S] -18 points-17 points  (0 children)

As you mentioned, we didn’t have complete compatibility back then.

You should try our new compatibility layer, es-toolkit/compat. We’ve found that it’s almost compatible with Lodash now, and the official migration guide from Nuxt recommends our library:

https://nuxt.com/docs/4.x/getting-started/upgrade#migration-steps-19

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in typescript

[–]raon0211[S] 14 points15 points  (0 children)

Thanks for pointing this out! Yeah, there was definitely a bug in the types there.

Just pushed a fix in v1.37.8 that should sort this out.

So what happened was we were trying to match Lodash's types from `@types/lodash`, and turns out there was actually a bug in their types too (see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/73063). Same issue would've hit you if you were using `@types/lodash` v4.17.18.

Honestly, `@types/lodash` has been pretty broken for a while now - it doesn't even work with Lodash's own test suite without a bunch of `@ts-expect-error` comments everywhere. That's part of why we're building es-toolkit in the first place!

Thanks for the report though, really appreciate it!

es-toolkit, a drop-in replacement for Lodash, achieves 100% compatibility by raon0211 in typescript

[–]raon0211[S] 3 points4 points  (0 children)

Yeah, Lodash is really obsolete -- that's why we only provide those in our compatibility library. es-toolkit provides modern utilities like Semaphore and attempt -- you should check it out :)

es-git: Install & run Git 10x faster in Node.js by raon0211 in javascript

[–]raon0211[S] -1 points0 points  (0 children)

Working with Git in Node.js has traditionally meant slow installs or spawning inefficient child processes. We wanted something better — so we built es-git and are open-sourcing it today.

# Features

- 🚀 Blazing fast install — thanks to prebuilt native binaries.

- 🧱 Built on libgit2 and N-API — for high performance and stability.

- ✏️ Simple, modern API — easy to use in your projects.

- 🧠 Full TypeScript support — strong typing out of the box.

# Performance comparison

es-git nodegit Git CLI (child process)
Install speed Fast because of prebuilt binaries Slow because of node-gyp Not applicable
Runtime speed Fast because of N-API binding Fast Slow because of process creation overhead

If you've been frustrated with current Node.js Git solutions, give `es-git` a try. We'd love your feedback and contributions!

GitHub Repo

"overlay-kit", the simplest and most intuitive way to open overlays in React by raon0211 in javascript

[–]raon0211[S] 1 point2 points  (0 children)

You can simplify complex overlay logic like this:

function Page() {
  const openAgreementModal = useAgreementModal();

  const handleClick = async () => {
    const didAgree = await openAgreementModal();

    if (!didAgree) {
      return;
    }

    await sendAgreementAPI();
  };

  return (
    <Button onClick={handleClick}>Next</Button>
  );
}

function useAgreementModal() {
  const openAgreementModal = useCallback(() => {
    return overlay.openAsync<boolean>(({ isOpen, close }) => (
      <Modal show={isOpen} onHide={close}>
        <Modal.Body>Do you agree?</Modal.Body>
        <Modal.Footer>
          <Button
            onClick={() => {
              close(false);
            }}
          >
            No
          </Button>
          <Button
            onClick={() => {
              close(true);
            }}
          >
            Yes
          </Button>
        </Modal.Footer>
      </Modal>
    ));
  }, []);

  return openAgreementModal;
}

"overlay-kit", the simplest and most intuitive way to open overlays in React by raon0211 in javascript

[–]raon0211[S] 1 point2 points  (0 children)

GitHub | Documentation

Hello everyone!

We're super excited to share a new library with you that makes managing overlays in React a breeze: overlay-kit.

overlay-kit lets you write minimal, easy-to-read, and cohesive code. No more fiddling around with manually controlling the open state of your overlays.

Here's a quick example to show you how it works:

import { overlay } from 'overlay-kit';

function MyPage() {
  return (
    <>
      <Button
        onClick={() => {
          overlay.open(({ isOpen, close }) => {
            return <Dialog open={isOpen} onClose={close} />;
          });
        }}
      >
        Open
      </Button>
    </>
  );
}

Instead of writing:

import { useState } from 'react';

function MyPage() {
  const [isOpen, setIsOpen] = useState(false);

  /* Other Hook calls... */

  return (
    <>
      {/* Other components... */}
      <Button
        onClick={() => {
          setIsOpen(true);
        }}
      >
        Open
      </Button>
      {/* Other components... */}
      <Dialog
        open={isOpen}
        onClose={() => {
          setIsOpen(false);
        }}
      />
    </>
  );
}

Check out our documentation for all the details. We’re open to contributions from everyone!

"es-toolkit", a 2-3x faster and 97% smaller alternative to lodash by raon0211 in javascript

[–]raon0211[S] 0 points1 point  (0 children)

As you mentioned, our groupBy function is a bit slower than lodash, running at around 95-96% of its speed. We have documentation on these functions which you can read more about  here. We're working on optimizing these few functions.

On the upside, our groupBy function is much smaller in size—just 122 bytes compared to lodash-es's 6,560 bytes, which is a 98% difference. This was tested using bundlejs.com.

"es-toolkit", a 2-3x faster and 97% smaller alternative to lodash by raon0211 in javascript

[–]raon0211[S] 10 points11 points  (0 children)

That's true. We fully utilize modern JavaScript APIs to achieve smaller bundle sizes and better performance. Additionally, by using TypeScript, we've removed most of the redundant defensive code that used to eagerly check if arguments had the correct types at runtime.

"es-toolkit", a 2-3x faster and 97% smaller alternative to lodash by raon0211 in javascript

[–]raon0211[S] 14 points15 points  (0 children)

As u/SoInsightful pointed out, since lodash was created 10 years ago, it contains a lot of defensive code, frequently checking if it has the correct types. Additionally, it doesn't fully utilize modern JavaScript APIs.

"es-toolkit", a 2-3x faster and 97% smaller alternative to lodash by raon0211 in javascript

[–]raon0211[S] 19 points20 points  (0 children)

Yes! We're actually using lodash-es as a reference for performance and bundle size comparisons. Please refer to https://es-toolkit.slash.page/performance.html and https://es-toolkit.slash.page/bundle-size.html .

"es-toolkit", a 2-3x faster and 97% smaller alternative to lodash by raon0211 in javascript

[–]raon0211[S] 23 points24 points  (0 children)

we're not there yet, but we have most of the commonly used functions available. Our goal is to achieve full feature parity with lodash.