Things to keep in mind when using Lodash
Here are some things you should keep in mind if you use or want to use Lodash in your app.
Why you should use Lodash
Lodash provides all kinds of utilities. For this reason, you won’t need to spend a lot of time writing your own helpers and tests for the same.
Lodash utilities are also 'safe', meaning they will try their best to handle edge cases and not throw errors. To demonstrate, let's say you need to map over an array of products to get an array with just their codes.
You could use JS’s Array.prototype.map
.
The problem is that if the array you need to apply it on isn’t coming from a predictable data source, say from an external API, and if you don’t correctly handle that edge case, it could crash your application with a dreaded error message.
This problem could be mitigated if you used Lodash’s map
. This map
is very similar to Array.prototype.map
.
If products
was null or undefined or a primitive, it would just return an empty array. Since any code using your productCodes
array would be expecting an array, everything from this point on would continue working without crashing.
Similarly, fetching nested data is really easy with Lodash's get
.
To sum up, Lodash is great for two reasons:
Chaining operations
Although Lodash does help you write cleaner code by wrapping things like loops and conditionals inside functions with readable names, sometimes you may need to perform a sequence of operations on some data, processing it in stages.
Let’s say you have a list of customers. This list is represented by an array of objects.
You need to get a list of unique cities that the customers, between ages 21 and 30, belong to, so that you may then visualise those numbers on a map, displaying the cities in which your product is most popular.
You would probably write that code like so.
This quickly becomes cumbersome. You need to create a new variable at each step. You also need to name them, which is probably the second hardest problem in computer science.
If you were using vanilla JavaScript, you could use the Array prototype methods to an extent and chain them, as long as the previous one returned an array at every stage:
But what if you wanted to achieve the same thing in Lodash and reap all the benefits?
To do this, Lodash provides an extremely useful function called chain
. You could pass anything to chain, and it would return something that would contain the value that you passed, and methods for everything Lodash could do with that value.
How cool was that? At this point you really begin to see how clean your code can get.
But how does this even work?
Well, chain
kind of wraps your value inside an object, whose methods are the functions of Lodash, with the wrapped data as the first argument.
In the end, to get back the result, you would need to extract that wrapped value with value()
.
Sometimes it may harm you to use Lodash
It's true that Lodash functions are 'safe', so they won't throw errors easily. At the same time this can lead to logical errors that aren't detected simply because they did not throw errors.
Relying too much on Lodash could lead to poor programming practices and less thought towards error cases and how they should be handled.
Secondly, the implicit handling of edge cases by Lodash helpers could take the ability to handle errors out of your hands. Whether your code produces an array, an object, null or undefined, all those things mean something. But the helper, which is concerned with making things easier and more generic, coerces all of these things into one, in order to give a consistent output, even if it’s the wrong thing. Information is lost in this process.
In other words, since you aren't thinking too much about error handling anymore, you could end up with code that doesn't crash, but isn't correct either.
Execution time
Lodash functions take into account several data types and edge cases. As a result, they are sometimes large, end up calling other small utilities, or calling themselves recursively.
As a result, Lodash utilities can sometimes end up being quite a lot slower than their standard library counterparts, although this isn't always true (Lodash has optimisations for chained operations on very large collections).
Bundle size
The code you write isn’t always what finally runs in the browser or phone. Modern JS frameworks (and boilerplates like create-react-app
) use build pipelines that typically do the following:
The first step ensures the code can run on as many platforms as possible. Compilers like Babel handle this.
The second and third steps help to actually reduce the bundle size. They are handled by bundlers like Webpack and minifiers like Terser respectively.
Smaller bundle sizes mean smaller amounts of data flowing over the internet.
Less data means quicker load times.
The second step is where you could get in trouble with Lodash. Most tools that perform tree shaking, like Webpack and Rollup can pretty easily eliminate functions that are defined but not used.
Objects are hard though. JS objects are dynamic. So you can add and remove stuff like data and methods to objects on the fly at runtime. Due to the dynamic nature of objects, most tree shaking mechanisms either find it difficult to do it on objects, or simply don't bother doing it due to this fact. (Some part of the code may, after all, try to dynamically access a method on an object while iterating over its keys at runtime, for example. It's difficult to reason what parts should be eliminated.)
If you import Lodash like this:
you are importing ALL of Lodash. _
, the default export of Lodash, is an object. _.map
, _.filter
, _.get
and everything else are properties on this object, and your bundler won't be able to eliminate the stuff you don't use.
To prevent this, be careful with your imports.
Or if you have control over your build pipeline, use some plugin that can automatically optimise the imports at build time like babel-plugin-lodash.
Most importantly, if you import chain
, you end up implicitly importing all of Lodash and plugins won't help at all.
Prelude to part 2
Lodash has a lesser known module called fp
, which has almost all the utilities provided by Lodash, but each with a small twist that greatly enhances their capabilities.
fp
here stands for functional programming. The functions in lodash/fp
are designed to be used in a more functional style, with a particular emphasis on partial application.
The next part in this series will cover how you can use lodash/fp
to your advantage, and even use a function called flow
, as an alternative to chain
, while overcoming bundle size issues.
TL:DR
Here’s a quick recap of what we covered:
Afterword
Although it’s fun to find out cool stuff about development tools and libraries, and even more fun to put them to good use, it’s important to remember that as devs our goal should be to:
Book a Discovery Call.