Webpack plugin that creates smaller Lodash builds by replacing feature sets with noop, identity, or simpler alternatives.
npx @tessl/cli install tessl/npm-lodash-webpack-plugin@0.11.0The Lodash Webpack Plugin creates smaller Lodash builds by replacing feature sets of modules with noop, identity, or simpler alternatives. This plugin complements babel-plugin-lodash by shrinking cherry-picked builds even further through intelligent module replacement during the webpack bundling process.
npm install --save-dev lodash-webpack-plugin// CommonJS (recommended for webpack configs)
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');For ES modules:
// ES Modules (for modern bundlers)
import LodashModuleReplacementPlugin from 'lodash-webpack-plugin';Importing named exports:
// Access to data objects
import { features, overrides, stubs } from 'lodash-webpack-plugin';For Rollup integration:
// Rollup usage (function call, not constructor)
import Plugin from 'lodash-webpack-plugin';// webpack.config.js
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
module.exports = {
plugins: [
new LodashModuleReplacementPlugin(),
// ... other plugins
]
};With feature options:
// Enable specific features for more functionality
new LodashModuleReplacementPlugin({
'collections': true,
'paths': true,
'shorthands': true
});The plugin works by intercepting webpack's module resolution process:
normalModuleFactory to catch lodash module requestsMain plugin class for webpack integration.
/**
* Lodash Module Replacement Plugin for webpack
* @class
*/
class LodashModuleReplacementPlugin {
/**
* Creates a new LodashModuleReplacementPlugin instance
* @param {PluginOptions} [options={}] - Configuration options for feature sets
*/
constructor(options);
/**
* Array tracking module replacement matches performed during build
* @type {Array<Array<string>>} Array of [original, replacement] path pairs
*/
matches;
/**
* Plugin configuration options merged with defaults
* @type {PluginOptions}
*/
options;
/**
* Current replacement patterns based on disabled features
* @type {Array<Array<string>>}
*/
patterns;
/**
* Webpack plugin interface method that registers module resolution hooks
* @param {Object} compiler - Webpack compiler instance
* @param {Object} compiler.hooks - Webpack compiler hooks (webpack 4+)
* @param {Function} compiler.plugin - Legacy plugin method (webpack < 4)
*/
apply(compiler);
/**
* Core module resolution method that performs lodash module replacement
* @param {Object} resolveData - Webpack resolve data
* @param {string} resolveData.rawRequest - Original module request string
* @param {string} resolveData.resource - Resolved module file path
* @returns {string} Modified resource path if replacement found, otherwise original resource
*/
resolve({ rawRequest, resource });
}Dual-mode function that works as both webpack plugin constructor and rollup plugin factory.
/**
* Main export function with dual behavior:
* - When called with 'new' (webpack): Returns LodashModuleReplacementPlugin instance
* - When called directly (rollup): Returns modified nodeResolve plugin with lodash replacement
* @param {Object|PluginOptions} nodeResolveOrOptions - For webpack: options object; For rollup: nodeResolve plugin instance
* @param {PluginOptions} [options] - For rollup: configuration options for feature sets
* @returns {LodashModuleReplacementPlugin|Object} Plugin instance or modified resolve plugin
*/
function Plugin(nodeResolveOrOptions, options);Alternative interface for rollup bundler integration.
/**
* Creates a rollup plugin with lodash module replacement functionality
* @param {Object} nodeResolve - Rollup node resolve plugin instance
* @param {PluginOptions} options - Configuration options for feature sets
* @returns {Object} Modified resolve plugin with lodash replacement
*/
function Plugin(nodeResolve, options);Feature-based configuration system for controlling module replacements.
/**
* Plugin configuration options
* @typedef {Object} PluginOptions
* @property {boolean} [caching] - Enable caching features (_.cloneDeep, _.isEqual, _.uniq)
* @property {boolean} [chaining] - Enable chain sequence components
* @property {boolean} [cloning] - Enable clone methods and cloning source objects
* @property {boolean} [coercions] - Enable value coercion to integers, numbers, strings
* @property {boolean} [collections] - Enable object support in Collection methods
* @property {boolean} [currying] - Enable curry methods
* @property {boolean} [deburring] - Enable deburring letters support
* @property {boolean} [exotics] - Enable support for buffers, maps, sets, symbols, typed arrays
* @property {boolean} [flattening] - Enable flatten methods and flattening rest arguments
* @property {boolean} [guards] - Enable guards for host objects, sparse arrays, edge cases
* @property {boolean} [memoizing] - Enable _.memoize and memoization support
* @property {boolean} [metadata] - Enable metadata to reduce wrapping (requires currying)
* @property {boolean} [paths] - Enable deep property path support (_.get, _.has, _.set)
* @property {boolean} [placeholders] - Enable argument placeholder support (requires currying)
* @property {boolean} [shorthands] - Enable iteratee shorthands (_.property, _.matches, _.matchesProperty)
* @property {boolean} [unicode] - Enable Unicode symbols support
*/The plugin replaces lodash modules based on feature sets. By default, all features are disabled for maximum size reduction.
/**
* Available feature sets mapping
* @type {Object<string, Array<Array<string>>>}
*/
const features = {
'caching': [
['_baseIndexOf', '_strictIndexOf'],
['_cacheHas', '_arrayIncludes'],
['_createSet', 'noop'],
['_MapCache', '_ListCache'],
['_SetCache', 'castArray'],
['_Stack', '_ListCache']
],
'chaining': [
['_getFuncName', 'stubString'],
['_isLaziable', 'stubFalse'],
['_LodashWrapper', 'noop']
],
'cloning': [
['_baseClone', 'identity']
],
'coercions': [
['_baseToNumber', 'identity'],
['_baseToString', 'identity'],
['_toKey', 'identity'],
['toFinite', 'identity'],
['toInteger', 'identity'],
['toLength', 'identity'],
['toNumber', 'identity'],
['toString', 'identity']
],
'collections': [
['_baseAggregator', '_arrayAggregator'],
['_baseFilter', '_arrayFilter'],
['_baseMap', '_arrayMap'],
['each', '_arrayEach'],
['eachRight', '_arrayEachRight'],
['every', '_arrayEvery'],
['filter', '_arrayFilter'],
['forEach', '_arrayEach'],
['forEachRight', '_arrayEachRight'],
['includes', '_arrayIncludes'],
['map', '_arrayMap'],
['reduce', '_arrayReduce'],
['reduceRight', '_arrayReduceRight'],
['sample', '_arraySample'],
['sampleSize', '_arraySampleSize'],
['shuffle', '_arrayShuffle'],
['some', '_arraySome']
],
'currying': [
['_createWrap', '_createPartial'],
['unary', '_baseUnary']
],
'deburring': [
['deburr', 'toString']
],
'exotics': [
['_baseGetTag', '_objectToString'],
['_equalByTag', 'eq'],
['_getAllKeys', '_nativeKeys'],
['_getAllKeysIn', '_nativeKeysIn'],
['_getSymbols', 'stubArray'],
['_getSymbolsIn', 'stubArray'],
['_getTag', '_objectToString'],
['_initCloneByTag', 'identity'],
['_mapToArray', 'stubArray'],
['_setToArray', 'stubArray'],
['_setToPairs', 'stubArray'],
['isArguments', 'stubFalse'],
['isArrayBuffer', 'baseIsArrayBuffer'],
['isBuffer', 'stubFalse'],
['isDate', 'baseIsDate'],
['isMap', 'stubFalse'],
['isRegExp', 'baseIsRegExp'],
['isSet', 'stubFalse'],
['isSymbol', 'stubFalse'],
['isTypedArray', 'stubFalse']
],
'flattening': [
['_baseFlatten', 'head'],
['_flatRest', 'identity']
],
'guards': [
['_getNative', '_getValue'],
['_getRawTag', '_objectToString'],
['_isIterateeCall', 'stubFalse'],
['_isPrototype', 'stubFalse'],
['_baseKeys', '_nativeKeys'],
['_baseKeysIn', '_nativeKeysIn'],
['_castFunction', 'identity'],
['_castRest', 'identity'],
['_shortOut', 'identity'],
['isNaN', 'baseIsNaN'],
['isNative', 'stubTrue'],
['keys', '_nativeKeys'],
['keysIn', '_nativeKeysIn'],
['times', '_baseTimes']
],
'memoizing': [
['_memoizeCapped', 'identity'],
['memoize', 'identity']
],
'metadata': [
['_baseSetData', 'identity'],
['_getData', 'noop'],
['_mergeData', 'identity'],
['_setData', 'identity'],
['_setToString', 'identity'],
['_setWrapToString', 'identity']
],
'paths': [
['_baseGet', '_getValue'],
['_castPath', 'castArray'],
['_isKey', 'identity'],
['_parent', 'identity'],
['has', '_baseHas'],
['hasIn', '_baseHasIn'],
['property', '_baseProperty'],
['propertyOf', '_basePropertyOf']
],
'placeholders': [
['_getHolder', 'noop'],
['_replaceHolders', 'stubArray']
],
'shorthands': [
['_baseIteratee', 'identity']
],
'unicode': [
['_hasUnicode', 'stubFalse'],
['_hasUnicodeWord', 'stubFalse'],
['_unicodeSize', '_asciiSize'],
['_unicodeToArray', '_asciiToArray'],
['_unicodeWords', '_asciiWords'],
['stringSize', '_asciiSize'],
['stringToArray', '_asciiToArray']
]
};Certain lodash methods automatically enable required features regardless of global settings.
/**
* Method-specific feature requirements
* @type {Object<string, Object>}
*/
const overrides = {
'ary': { 'currying': true },
'camelCase': { 'unicode': true },
'clone': { 'cloning': true },
'cloneDeep': { 'cloning': true },
'cloneDeepWith': { 'cloning': true },
'cloneWith': { 'cloning': true },
'concat': { 'flattening': true },
'curry': { 'currying': true },
'curryRight': { 'currying': true },
'difference': { 'flattening': true },
'differenceBy': { 'flattening': true },
'differenceWith': { 'flattening': true },
'fill': { 'coercions': true },
'flatMap': { 'flattening': true },
'flatMapDeep': { 'flattening': true },
'flatMapDepth': { 'flattening': true },
'flatten': { 'flattening': true },
'flattenDeep': { 'flattening': true },
'flattenDepth': { 'flattening': true },
'flip': { 'currying': true },
'isInteger': { 'coercions': true },
'kebabCase': { 'unicode': true },
'lowerCase': { 'unicode': true },
'parseInt': { 'coercions': true },
'partialRight': { 'currying': true },
'pick': { 'paths': true },
'rearg': { 'currying': true },
'snakeCase': { 'unicode': true },
'startCase': { 'unicode': true },
'union': { 'flattening': true },
'unionBy': { 'flattening': true },
'unionWith': { 'flattening': true },
'uniqueId': { 'coercions': true },
'upperCase': { 'unicode': true },
'xor': { 'flattening': true },
'xorBy': { 'flattening': true },
'xorWith': { 'flattening': true }
};List of lodash stub functions used as lightweight replacement targets.
/**
* Available stub functions for module replacement
* @type {string[]}
*/
const stubs = [
'identity',
'noop',
'stubArray',
'stubFalse',
'stubObject',
'stubString',
'stubTrue'
];Core data structures exported from the plugin for external access.
/**
* Named export of feature sets mapping
* @type {Object<string, Array<Array<string>>>}
*/
export const features;
/**
* Named export of method-specific feature requirements
* @type {Object<string, Object>}
*/
export const overrides;
/**
* Named export of available stub functions
* @type {string[]}
*/
export const stubs;Internal functions and constants that power the plugin's functionality.
/**
* Generates replacement patterns based on disabled features
* @param {PluginOptions} options - Feature configuration options
* @returns {Array<Array<string>>} Array of [original, replacement] pairs
*/
function getPatterns(options);
/**
* Regular expression for matching lodash resource paths
* @type {RegExp}
*/
const reLodashRes;
/**
* Regular expression for matching explicit lodash module requests
* @type {RegExp}
*/
const reExplicitReq;
/**
* Path to lodash installation directory
* @type {string}
*/
const lodashRoot;normalModuleFactory.hooks.afterResolvereLodashRescreateData.resource for module resolutiondata.resource modificationplugin() callback-based APIresolveId method of node-resolve plugin with memoized resolutionThe plugin uses lodash's memoize function to cache resolution results based on the resource path, improving performance during builds by avoiding repeated pattern matching and file system checks.
// webpack.config.js - minimal setup
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
module.exports = {
module: {
rules: [{
use: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/,
options: {
plugins: ['lodash'],
presets: [['env', { modules: false }]]
}
}]
},
plugins: [
new LodashModuleReplacementPlugin(),
// ... other plugins
]
};// webpack.config.js - with selective features
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
module.exports = {
plugins: [
new LodashModuleReplacementPlugin({
// Enable collections support for object iteration
'collections': true,
// Enable path support for deep property access
'paths': true,
// Enable shorthands for property/matches shortcuts
'shorthands': true,
// Keep cloning disabled for smaller bundles (default: false)
'cloning': false
})
]
};// Using exported data objects
const { features, overrides, stubs } = require('lodash-webpack-plugin');
// Check available features
console.log('Available features:', Object.keys(features));
// Check method overrides
console.log('Methods with automatic overrides:', Object.keys(overrides));
// Check stub functions
console.log('Available stubs:', stubs);
// Create plugin with dynamic feature detection
const enabledFeatures = {};
if (needsCloning) enabledFeatures.cloning = true;
if (needsPaths) enabledFeatures.paths = true;
const plugin = new LodashModuleReplacementPlugin(enabledFeatures);
// Access plugin state after compilation
console.log('Replaced modules:', plugin.matches);// rollup.config.js
import Plugin from 'lodash-webpack-plugin';
import nodeResolve from '@rollup/plugin-node-resolve';
export default {
plugins: [
Plugin(nodeResolve(), {
'collections': true,
'paths': true
})
]
};metadata requires currying, placeholders requires currying)features, overrides, and stubs objects for external inspectionmatches property after compilation to see which modules were replaced