es-toolkit, a Lodash alternative

leemeganj

Megan Lee

Posted on November 13, 2024

es-toolkit, a Lodash alternative

Written by Rishi Purwar✏️

If you’ve been building JavaScript applications for a while, you’ve probably used utility libraries like Lodash. These libraries are packed with useful functions that make coding in JavaScript easier and more efficient. But as your project grows and you start using more utility functions, you might notice that your bundle size also starts increasing.

This is especially true when you rely on heavy libraries like Lodash, which makes you wonder if there is a better alternative.

That’s where es-toolkit comes in — a modern, high-performance JavaScript utility library that’s lightweight and comes with solid TypeScript support, making it a great alternative to popular libraries like Lodash.

These are the main comparisons between es-toolkit and Lodash:

  • es-toolkit offers key utility functions similar to Lodash, covering areas like functions, arrays, objects, strings, math, predicates, and promises
  • es-toolkit’s functions are often faster than Lodash’s because they use modern JavaScript APIs in their implementations and TypeScript for type checking, reducing the need for extra defensive code.
  • Performance benchmarks show that es-toolkit functions outperform Lodash equivalents, sometimes by significant margins
  • es-toolkit’s functions have significantly smaller bundle sizes compared to Lodash’s equivalents, leading to faster load times and better performance
  • es-toolkit addresses performance and bundle size challenges by leveraging modern JavaScript features and avoiding the interdependencies found in Lodash
  • es-toolkit functions are mostly standalone, preventing unintended inclusion of unnecessary code, unlike Lodash where utility functions are often interdependent

Let’s get into the nitty-gritty about these differences and see how you can use es-toolkit in your JavaScript projects.

Key features of es-toolkit

Here’s a quick look at what es-toolkit brings to the table:

  • Functions including memoize to cache function results and debounce to limit how often a function is called
  • Arrays like uniq to filter out duplicates and difference to find what’s different between arrays
  • Tools for handling JavaScript objects, such as cloneDeep for deep cloning and flattenObject to transform nested objects into a flat structure
  • String manipulation tools, including kebabCase to convert strings to kebab-case
  • Math helpers like random for generating random numbers and round for rounding them off
  • Type guard functions like isNil to easily check for null or undefined values
  • Utilities for working with asynchronous code, like delay to pause execution for a bit

Performance and bundle size comparison

To truly understand the benefits of es-toolkit, let's compare its performance and bundle size to Lodash.

Performance

es-toolkit’s functions are often faster than Lodash’s because they use modern JavaScript APIs in their implementations. For example, es-toolkit’s omit function is about 11.8 times faster than lodash’s omit function.

Here’s a table comparing the performance of es-toolkit and lodash-es for various functions:

Function es-toolkit@0.0.1 lodash-es@4.17.21 Difference
omit 4,767,360 times 403,624 times 11.8×
pick 9,121,839 times 2,663,072 times 3.43×
differenceWith 9,291,897 times 4,275,222 times 2.17×
difference 10,436,101 times 5,155,631 times 2.02×
intersectionWith 8,074,722 times 3,814,479 times 2.12×
intersection 9,999,571 times 4,630,316 times 2.15×
unionBy 6,435,983 times 3,794,899 times 1.69×
union 5,059,209 times 4,771,400 times 1.06×
dropRightWhile 7,529,559 times 5,606,439 times 1.34×
groupBy 5,000,235 times 5,206,286 times 0.96×

Bundle size

When it comes to bundle size, es-toolkit really shines. A smaller bundle size means your web applications will load faster and perform better, especially on slower networks.

Here’s a comparison of the bundle sizes for some common functions in es-toolkit and lodash-es:

Function es-toolkit@0.0.1 lodash-es@4.17.21 Difference
sample 88 bytes 2,000 bytes -95.6 percent
difference 91 bytes 3,190 bytes -97.2 percent
sum 152 bytes 413 bytes -63.2 percent
debounce 144 bytes 1,400 bytes -89.7 percent
throttle 110 bytes 1,460 bytes -92.5 percent
pick 657 bytes 3,860 bytes -83.0 percent
zip 797 bytes 1,790 bytes -55.5 percent

es-toolkit’s functions are much smaller compared to their Lodash counterparts. For instance, the sample function in es-toolkit is only 88 bytes, whereas the same function in Lodash is 2,000 bytes — nearly 96 percent smaller!

Using es-toolkit in a JavaScript app

Let’s look into some examples to see how easy it is to use es-toolkit in a JavaScript application. In this section, we’ll explore how es-toolkit handles common tasks like debouncing, throttling, picking specific properties from objects, and removing duplicates from an array.

And guess what? To make things even easier, I’ve put together a starter code repository on GitHub that you can clone and start experimenting with right away. You’ll find the HTML and CSS code for all the examples we will cover, along with everything you need to get started. Check out the repo here and follow along.

Debounce example

Let’s say you’re building a search feature for a website where users can look up information on different topics.

You want to fetch data as the user types but without sending a request for every single keystroke; otherwise, you might flood the API with too many calls. That’s where the debounce function from es-toolkit comes in handy.

Here’s how it works:

import { debounce } from "es-toolkit";

// a function that simulates an API call
function fetchData(query) {
  console.log(`Fetching data for: ${query}`);
}

// Using es-toolkit debounce function
const debouncedFetchData = debounce(fetchData, 1000);

document.getElementById("search-input").addEventListener("input", (event) => {
    const query = event.target.value;
    debouncedSearch(query);
});
Enter fullscreen mode Exit fullscreen mode

In the below demo, even though I typed out five letters, the fetchData function only gets called after I’ve stopped typing for a second.

This way, we can avoid making unnecessary API requests on every keypress using the debounce function.
Debounce example demonstrating the search input field using es-toolkit to prevent multiple API requests with each keystroke.  

Throttle example

Suppose you have a button on your webpage that loads more posts when clicked. To prevent multiple API calls if the button is clicked too quickly, you can use the throttle function from es-toolkit. It ensures the API call happens only at set intervals, even if the button is clicked several times.

Here’s how you can use it:

// Throttle Example
import { throttle } from "es-toolkit";

// Function to fetch posts from an API
async function fetchPosts() {
  console.log("Fetching new posts...");
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  const posts = await response.json();
  console.log("Posts fetched:", posts);
}
// Create a throttled version of fetchPosts
const throttledFetchPosts = throttle(fetchPosts, 2000);

// Set up an event listener on the button
document.getElementById("fetch-more-posts").addEventListener("click", () => {
  console.log("button clicked");
  throttledFetchPosts();
});
Enter fullscreen mode Exit fullscreen mode

In this example, even if a user clicks the “Fetch More Posts” button rapidly, the fetchPosts function will only be triggered once every two seconds, as shown in the demo below.
Throttle example showing the  

Pick example

Let’s say you have detailed user profile data, but you only want to display specific properties like username, email, and age in the user summary component. The pick function helps you extract these properties easily.

Here’s a demonstration of how it works:

// Pick Example
import { pick } from "es-toolkit";

// dummy user data
const user = {
  id: 1,
  username: "johndoe",
  firstName: "John",
  lastName: "Doe",
  email: "john.doe@example.com",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown",
    country: "USA",
  },
  phoneNumber: "1234-5678",
};

// Use pick to select specific properties
const pickedUser = pick(user, ["username", "email", "age"]);

console.log("pickedUser", pickedUser)
Enter fullscreen mode Exit fullscreen mode

In this example, the pick function extracts the username, email, and age properties from the user object. The console log will output:

pickedUser: { username: 'johndoe', email: 'john.doe@example.com', age: 30 }
Enter fullscreen mode Exit fullscreen mode

Uniq example

Imagine you’re running a blog where users can add tags to categorize their posts. You want to make sure that each tag only appears once. This is where the uniq function from es-toolkit is super useful. It helps you filter out duplicates from an array and get a list of unique tags.

Here’s a practical example:

>import { uniq } from "es-toolkit";

// Array of tags with some duplicates
const tags = [
  "javascript",
  "coding",
  "webdev",
  "programming",
  "javascript",
  "react",
  "nodejs",
  "coding",
  "html",
  "css",
  "webdev",
  "frontend",
];

// Use uniq to filter out duplicate tags
const uniqueTags = uniq(tags);

console.log("uniqueTags", uniqueTags);
Enter fullscreen mode Exit fullscreen mode

In the above example, the uniq function removes duplicates from the tags array. The console log will output:

uniqueTags: ['javascript', 'coding', 'webdev', 'programming', 'react', 'nodejs', 'html', 'css', 'frontend']
Enter fullscreen mode Exit fullscreen mode

How es-toolkit addresses performance and bundle size challenges

You might be curious about how es-toolkit tackles these challenges. Under the hood, es-toolkit leverages modern JavaScript APIs to deliver faster performance and significantly smaller bundle sizes.

On top of that, es-toolkit uses TypeScript, which helps cut out a lot of the extra defensive code that usually checks argument types at runtime. This not only makes the code run more efficiently but also minimizes any unnecessary overhead that can slow things down.

Another key difference is that Lodash utility functions are often interdependent, meaning that importing one function can drag in many others along with it. In contrast, es-toolkit functions are mostly standalone, which helps keep your bundle lightweight.

To really see the difference, you can use webpack-bundle-analyzer to visualize the size of your bundle. I've set everything up for you, so all you need to do is checkout to main branch and run npm i && npm run build from the root of the cloned repository, and it will open a page with all the details about your bundle.

The image below shows the bundle size when using es-toolkit. You can see that most es-toolkit functions are standalone, which results in smaller bundle sizes.

Bundle size visualization showing es-toolkit dependencies, with smaller and standalone modules contributing to a reduced bundle size.  

Now, let's replace es-toolkit with lodash-es in the import statements from the examples above and run npm run build again to check the lodash-es bundle size.

The image below shows that Lodash functions are mostly interdependent, pulling in many other utilities when importing just one:

Bundle size visualization showing lodash dependencies, with modules interconnected and contributing to a larger overall bundle size.  

Conclusion

es-toolkit can be a great alternative to utility libraries like Lodash, especially when performance and bundle size are key considerations. Its small bundle size, modern JavaScript features usage, and solid TypeScript support make it an excellent choice for developers.

I hope you found this exploration of es-toolkit helpful for your JavaScript projects, but don’t stop here! I encourage you to try out es-toolkit in your own applications and share your experiences with us in the comments below. Happy coding!


Are you adding new JS libraries to improve performance or build new features? What if they’re doing the opposite?

There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.

LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.

LogRocket Signup Banner

LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.

Build confidently — Start monitoring for free.

💖 💪 🙅 🚩
leemeganj
Megan Lee

Posted on November 13, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related