Aggregating Cherry-Picked Lodash Methods In An Application Module In JavaScript

In an effort to build smaller and smaller JavaScript bundles with tools like Webpack, Rollup, and Browserify, web developers have started to forego full imports of libraries like Lodash; and, instead, are just cherry-picking (importing) individual methods out of the Lodash library. This way, when the bundler does its bundling, it only pulls in the isolated methods instead of the entire parent library. I think this is a noble effort. However, I rather dislike having my modules littered with esoteric variable names. And, to be honest, I miss having a single import for my utilities. As such, I've started to create a local application module that aggregates all of the cherry-picked Lodash methods.

NOTE: My examples happen to use TypeScript, but the theory should be the same regardless of technology choice.

Before aggregating Lodash methods, the use of cherry-picked methods might look something like this:

import find = require( "lodash/find" ); import without = require( "lodash/without" ); // ... var item = find( collection, [ "id", id ] ), // ... collection = without( collection, item ); // ... var item = find( collection, [ "name", name ] ), // ...

As you can see, the find() and without() Lodash methods are being imported individually and then used unscoped in the body of the current module. This totally works. I just don't care for it. I find it harder to read because I don't get to leverage the years of practice I have seeing the "_" variable (and all that it entails). I also find it harder to comprehend how much of Lodash is being used by my application. At first, this may not seem important; however, if I want to factor-out my vendor imports using Webpack, understanding the points of Lodash integration is certainly important.

To find a happy middle-ground, where we walk away with smaller JavaScript bundles without sacrificing the organization of our utilities, I've started moving the cherry-pick imports to a local module I'm calling "lodash-extended" (inspired by Bluebird's "bludbird-extended" philosophy):

import find = require( "lodash/find" ); import random = require( "lodash/random" ); import range = require( "lodash/range" ); import without = require( "lodash/without" ); // Repackage and export the individual lodash functions. // -- // *********************************************************************************** !! // *********************************************************************************** !! // IMPORTANT READ ME: When you add methods to this list, you must ALSO add them to the // vendor file (main.vedor.ts). This way, as methods get added here, Webpack will know // that they are not application-core methods and can factor them out into a versioned // vendor module, which will help with HTTP caching. // *********************************************************************************** !! // *********************************************************************************** !! export var _ = { find, random, range, without };

As you can see, this Lodash-extended module is little more than glue around the cherry-picked Lodash methods. But, it forces me to understand the app/lodash integration in an important way (for bundle delineation). And, it brings me back to a place where I only need one import to get my utilities:

import { _ } from "./lodash-extended"; // ... var item = _.find( collection, [ "id", id ] ), // ... collection = _.without( collection, item ); // ... var item = _.find( collection, [ "name", name ] ), // ...

To me, this is nice. I understand that this is totally subjective. But, this is what my brain likes. And, not only does it make it easier for me to consume the utilities, it also makes it easier for me to keep my bundles up-to-date because my lodash-extended module will mirror (in part) my vendor file:

// Import these libraries for their side-effects. // -- // CAUTION: As you add more "import" statements to your application code, you will have // to come back to this file and add those imports here as well (otherwise that imported // content may get bundled with your main application bundle, not your vendor bundle. import "lodash/find"; import "lodash/random"; import "lodash/range"; import "lodash/without";

And, of course, having a lodash-extended module gives me a nice place to add any additional functions - not provided by lodash - that would benefit my application in a generic way.

Smaller JavaScript bundles are nice. But, creating smaller bundles doesn't mean that we have to sacrifice packaging and established mental models. Aggregating cherry-picked Lodash methods in an application module gives us many of the normal benefits of a cohesive package with only a few lines of additional code. And, it gives us the added benefit of "just the right amount of friction" that will make it easier to keep our vendor files up-to-date.

Tweet This Groovy post by @BenNadel - Aggregating Cherry-Picked Lodash Methods In An Application Module In JavaScript Woot woot — you rock the party that rocks the body!







