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.00
# Lodash Webpack Plugin
1
2
The 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.
3
4
## Package Information
5
6
- **Package Name**: lodash-webpack-plugin
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install --save-dev lodash-webpack-plugin`
10
11
## Core Imports
12
13
```javascript
14
// CommonJS (recommended for webpack configs)
15
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
16
```
17
18
For ES modules:
19
20
```javascript
21
// ES Modules (for modern bundlers)
22
import LodashModuleReplacementPlugin from 'lodash-webpack-plugin';
23
```
24
25
Importing named exports:
26
27
```javascript
28
// Access to data objects
29
import { features, overrides, stubs } from 'lodash-webpack-plugin';
30
```
31
32
For Rollup integration:
33
34
```javascript
35
// Rollup usage (function call, not constructor)
36
import Plugin from 'lodash-webpack-plugin';
37
```
38
39
## Basic Usage
40
41
```javascript
42
// webpack.config.js
43
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
44
45
module.exports = {
46
plugins: [
47
new LodashModuleReplacementPlugin(),
48
// ... other plugins
49
]
50
};
51
```
52
53
With feature options:
54
55
```javascript
56
// Enable specific features for more functionality
57
new LodashModuleReplacementPlugin({
58
'collections': true,
59
'paths': true,
60
'shorthands': true
61
});
62
```
63
64
## Architecture
65
66
The plugin works by intercepting webpack's module resolution process:
67
68
- **Module Resolution Hook**: Integrates with webpack's `normalModuleFactory` to catch lodash module requests
69
- **Pattern Matching**: Uses regular expressions to identify lodash modules during resolution
70
- **Feature-based Replacement**: Replaces modules with lighter alternatives based on disabled feature sets
71
- **Webpack Version Compatibility**: Supports webpack 2, 3, 4, and 5 with version-specific hooks
72
- **Rollup Support**: Provides alternative interface for rollup bundler integration
73
74
## Capabilities
75
76
### Webpack Plugin
77
78
Main plugin class for webpack integration.
79
80
```javascript { .api }
81
/**
82
* Lodash Module Replacement Plugin for webpack
83
* @class
84
*/
85
class LodashModuleReplacementPlugin {
86
/**
87
* Creates a new LodashModuleReplacementPlugin instance
88
* @param {PluginOptions} [options={}] - Configuration options for feature sets
89
*/
90
constructor(options);
91
92
/**
93
* Array tracking module replacement matches performed during build
94
* @type {Array<Array<string>>} Array of [original, replacement] path pairs
95
*/
96
matches;
97
98
/**
99
* Plugin configuration options merged with defaults
100
* @type {PluginOptions}
101
*/
102
options;
103
104
/**
105
* Current replacement patterns based on disabled features
106
* @type {Array<Array<string>>}
107
*/
108
patterns;
109
110
/**
111
* Webpack plugin interface method that registers module resolution hooks
112
* @param {Object} compiler - Webpack compiler instance
113
* @param {Object} compiler.hooks - Webpack compiler hooks (webpack 4+)
114
* @param {Function} compiler.plugin - Legacy plugin method (webpack < 4)
115
*/
116
apply(compiler);
117
118
/**
119
* Core module resolution method that performs lodash module replacement
120
* @param {Object} resolveData - Webpack resolve data
121
* @param {string} resolveData.rawRequest - Original module request string
122
* @param {string} resolveData.resource - Resolved module file path
123
* @returns {string} Modified resource path if replacement found, otherwise original resource
124
*/
125
resolve({ rawRequest, resource });
126
}
127
```
128
129
### Default Export Function
130
131
Dual-mode function that works as both webpack plugin constructor and rollup plugin factory.
132
133
```javascript { .api }
134
/**
135
* Main export function with dual behavior:
136
* - When called with 'new' (webpack): Returns LodashModuleReplacementPlugin instance
137
* - When called directly (rollup): Returns modified nodeResolve plugin with lodash replacement
138
* @param {Object|PluginOptions} nodeResolveOrOptions - For webpack: options object; For rollup: nodeResolve plugin instance
139
* @param {PluginOptions} [options] - For rollup: configuration options for feature sets
140
* @returns {LodashModuleReplacementPlugin|Object} Plugin instance or modified resolve plugin
141
*/
142
function Plugin(nodeResolveOrOptions, options);
143
```
144
145
### Rollup Plugin Support
146
147
Alternative interface for rollup bundler integration.
148
149
```javascript { .api }
150
/**
151
* Creates a rollup plugin with lodash module replacement functionality
152
* @param {Object} nodeResolve - Rollup node resolve plugin instance
153
* @param {PluginOptions} options - Configuration options for feature sets
154
* @returns {Object} Modified resolve plugin with lodash replacement
155
*/
156
function Plugin(nodeResolve, options);
157
```
158
159
### Plugin Configuration
160
161
Feature-based configuration system for controlling module replacements.
162
163
```javascript { .api }
164
/**
165
* Plugin configuration options
166
* @typedef {Object} PluginOptions
167
* @property {boolean} [caching] - Enable caching features (_.cloneDeep, _.isEqual, _.uniq)
168
* @property {boolean} [chaining] - Enable chain sequence components
169
* @property {boolean} [cloning] - Enable clone methods and cloning source objects
170
* @property {boolean} [coercions] - Enable value coercion to integers, numbers, strings
171
* @property {boolean} [collections] - Enable object support in Collection methods
172
* @property {boolean} [currying] - Enable curry methods
173
* @property {boolean} [deburring] - Enable deburring letters support
174
* @property {boolean} [exotics] - Enable support for buffers, maps, sets, symbols, typed arrays
175
* @property {boolean} [flattening] - Enable flatten methods and flattening rest arguments
176
* @property {boolean} [guards] - Enable guards for host objects, sparse arrays, edge cases
177
* @property {boolean} [memoizing] - Enable _.memoize and memoization support
178
* @property {boolean} [metadata] - Enable metadata to reduce wrapping (requires currying)
179
* @property {boolean} [paths] - Enable deep property path support (_.get, _.has, _.set)
180
* @property {boolean} [placeholders] - Enable argument placeholder support (requires currying)
181
* @property {boolean} [shorthands] - Enable iteratee shorthands (_.property, _.matches, _.matchesProperty)
182
* @property {boolean} [unicode] - Enable Unicode symbols support
183
*/
184
```
185
186
### Feature Sets
187
188
The plugin replaces lodash modules based on feature sets. By default, all features are disabled for maximum size reduction.
189
190
```javascript { .api }
191
/**
192
* Available feature sets mapping
193
* @type {Object<string, Array<Array<string>>>}
194
*/
195
const features = {
196
'caching': [
197
['_baseIndexOf', '_strictIndexOf'],
198
['_cacheHas', '_arrayIncludes'],
199
['_createSet', 'noop'],
200
['_MapCache', '_ListCache'],
201
['_SetCache', 'castArray'],
202
['_Stack', '_ListCache']
203
],
204
'chaining': [
205
['_getFuncName', 'stubString'],
206
['_isLaziable', 'stubFalse'],
207
['_LodashWrapper', 'noop']
208
],
209
'cloning': [
210
['_baseClone', 'identity']
211
],
212
'coercions': [
213
['_baseToNumber', 'identity'],
214
['_baseToString', 'identity'],
215
['_toKey', 'identity'],
216
['toFinite', 'identity'],
217
['toInteger', 'identity'],
218
['toLength', 'identity'],
219
['toNumber', 'identity'],
220
['toString', 'identity']
221
],
222
'collections': [
223
['_baseAggregator', '_arrayAggregator'],
224
['_baseFilter', '_arrayFilter'],
225
['_baseMap', '_arrayMap'],
226
['each', '_arrayEach'],
227
['eachRight', '_arrayEachRight'],
228
['every', '_arrayEvery'],
229
['filter', '_arrayFilter'],
230
['forEach', '_arrayEach'],
231
['forEachRight', '_arrayEachRight'],
232
['includes', '_arrayIncludes'],
233
['map', '_arrayMap'],
234
['reduce', '_arrayReduce'],
235
['reduceRight', '_arrayReduceRight'],
236
['sample', '_arraySample'],
237
['sampleSize', '_arraySampleSize'],
238
['shuffle', '_arrayShuffle'],
239
['some', '_arraySome']
240
],
241
'currying': [
242
['_createWrap', '_createPartial'],
243
['unary', '_baseUnary']
244
],
245
'deburring': [
246
['deburr', 'toString']
247
],
248
'exotics': [
249
['_baseGetTag', '_objectToString'],
250
['_equalByTag', 'eq'],
251
['_getAllKeys', '_nativeKeys'],
252
['_getAllKeysIn', '_nativeKeysIn'],
253
['_getSymbols', 'stubArray'],
254
['_getSymbolsIn', 'stubArray'],
255
['_getTag', '_objectToString'],
256
['_initCloneByTag', 'identity'],
257
['_mapToArray', 'stubArray'],
258
['_setToArray', 'stubArray'],
259
['_setToPairs', 'stubArray'],
260
['isArguments', 'stubFalse'],
261
['isArrayBuffer', 'baseIsArrayBuffer'],
262
['isBuffer', 'stubFalse'],
263
['isDate', 'baseIsDate'],
264
['isMap', 'stubFalse'],
265
['isRegExp', 'baseIsRegExp'],
266
['isSet', 'stubFalse'],
267
['isSymbol', 'stubFalse'],
268
['isTypedArray', 'stubFalse']
269
],
270
'flattening': [
271
['_baseFlatten', 'head'],
272
['_flatRest', 'identity']
273
],
274
'guards': [
275
['_getNative', '_getValue'],
276
['_getRawTag', '_objectToString'],
277
['_isIterateeCall', 'stubFalse'],
278
['_isPrototype', 'stubFalse'],
279
['_baseKeys', '_nativeKeys'],
280
['_baseKeysIn', '_nativeKeysIn'],
281
['_castFunction', 'identity'],
282
['_castRest', 'identity'],
283
['_shortOut', 'identity'],
284
['isNaN', 'baseIsNaN'],
285
['isNative', 'stubTrue'],
286
['keys', '_nativeKeys'],
287
['keysIn', '_nativeKeysIn'],
288
['times', '_baseTimes']
289
],
290
'memoizing': [
291
['_memoizeCapped', 'identity'],
292
['memoize', 'identity']
293
],
294
'metadata': [
295
['_baseSetData', 'identity'],
296
['_getData', 'noop'],
297
['_mergeData', 'identity'],
298
['_setData', 'identity'],
299
['_setToString', 'identity'],
300
['_setWrapToString', 'identity']
301
],
302
'paths': [
303
['_baseGet', '_getValue'],
304
['_castPath', 'castArray'],
305
['_isKey', 'identity'],
306
['_parent', 'identity'],
307
['has', '_baseHas'],
308
['hasIn', '_baseHasIn'],
309
['property', '_baseProperty'],
310
['propertyOf', '_basePropertyOf']
311
],
312
'placeholders': [
313
['_getHolder', 'noop'],
314
['_replaceHolders', 'stubArray']
315
],
316
'shorthands': [
317
['_baseIteratee', 'identity']
318
],
319
'unicode': [
320
['_hasUnicode', 'stubFalse'],
321
['_hasUnicodeWord', 'stubFalse'],
322
['_unicodeSize', '_asciiSize'],
323
['_unicodeToArray', '_asciiToArray'],
324
['_unicodeWords', '_asciiWords'],
325
['stringSize', '_asciiSize'],
326
['stringToArray', '_asciiToArray']
327
]
328
};
329
```
330
331
### Method-specific Overrides
332
333
Certain lodash methods automatically enable required features regardless of global settings.
334
335
```javascript { .api }
336
/**
337
* Method-specific feature requirements
338
* @type {Object<string, Object>}
339
*/
340
const overrides = {
341
'ary': { 'currying': true },
342
'camelCase': { 'unicode': true },
343
'clone': { 'cloning': true },
344
'cloneDeep': { 'cloning': true },
345
'cloneDeepWith': { 'cloning': true },
346
'cloneWith': { 'cloning': true },
347
'concat': { 'flattening': true },
348
'curry': { 'currying': true },
349
'curryRight': { 'currying': true },
350
'difference': { 'flattening': true },
351
'differenceBy': { 'flattening': true },
352
'differenceWith': { 'flattening': true },
353
'fill': { 'coercions': true },
354
'flatMap': { 'flattening': true },
355
'flatMapDeep': { 'flattening': true },
356
'flatMapDepth': { 'flattening': true },
357
'flatten': { 'flattening': true },
358
'flattenDeep': { 'flattening': true },
359
'flattenDepth': { 'flattening': true },
360
'flip': { 'currying': true },
361
'isInteger': { 'coercions': true },
362
'kebabCase': { 'unicode': true },
363
'lowerCase': { 'unicode': true },
364
'parseInt': { 'coercions': true },
365
'partialRight': { 'currying': true },
366
'pick': { 'paths': true },
367
'rearg': { 'currying': true },
368
'snakeCase': { 'unicode': true },
369
'startCase': { 'unicode': true },
370
'union': { 'flattening': true },
371
'unionBy': { 'flattening': true },
372
'unionWith': { 'flattening': true },
373
'uniqueId': { 'coercions': true },
374
'upperCase': { 'unicode': true },
375
'xor': { 'flattening': true },
376
'xorBy': { 'flattening': true },
377
'xorWith': { 'flattening': true }
378
};
379
```
380
381
### Stub Functions
382
383
List of lodash stub functions used as lightweight replacement targets.
384
385
```javascript { .api }
386
/**
387
* Available stub functions for module replacement
388
* @type {string[]}
389
*/
390
const stubs = [
391
'identity',
392
'noop',
393
'stubArray',
394
'stubFalse',
395
'stubObject',
396
'stubString',
397
'stubTrue'
398
];
399
```
400
401
### Exported Data Objects
402
403
Core data structures exported from the plugin for external access.
404
405
```javascript { .api }
406
/**
407
* Named export of feature sets mapping
408
* @type {Object<string, Array<Array<string>>>}
409
*/
410
export const features;
411
412
/**
413
* Named export of method-specific feature requirements
414
* @type {Object<string, Object>}
415
*/
416
export const overrides;
417
418
/**
419
* Named export of available stub functions
420
* @type {string[]}
421
*/
422
export const stubs;
423
```
424
425
### Internal Utilities
426
427
Internal functions and constants that power the plugin's functionality.
428
429
```javascript { .api }
430
/**
431
* Generates replacement patterns based on disabled features
432
* @param {PluginOptions} options - Feature configuration options
433
* @returns {Array<Array<string>>} Array of [original, replacement] pairs
434
*/
435
function getPatterns(options);
436
437
/**
438
* Regular expression for matching lodash resource paths
439
* @type {RegExp}
440
*/
441
const reLodashRes;
442
443
/**
444
* Regular expression for matching explicit lodash module requests
445
* @type {RegExp}
446
*/
447
const reExplicitReq;
448
449
/**
450
* Path to lodash installation directory
451
* @type {string}
452
*/
453
const lodashRoot;
454
```
455
456
## Implementation Details
457
458
### Module Resolution Process
459
1. **Hook Registration**: Registers with webpack's `normalModuleFactory.hooks.afterResolve`
460
2. **Pattern Matching**: Tests resolved modules against lodash path patterns using `reLodashRes`
461
3. **Feature Checking**: Applies override rules for specific method requests from the overrides mapping
462
4. **File System Verification**: Checks for stub module existence before replacement
463
5. **Path Replacement**: Returns modified path or original if no replacement found
464
465
### Version Compatibility
466
- **Webpack 5.1+**: Uses `createData.resource` for module resolution
467
- **Webpack 4.x**: Uses direct `data.resource` modification
468
- **Webpack < 4**: Uses legacy `plugin()` callback-based API
469
- **Rollup**: Wraps `resolveId` method of node-resolve plugin with memoized resolution
470
471
### Memoization Behavior
472
The 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.
473
474
## Usage Examples
475
476
### Basic Webpack Configuration
477
478
```javascript
479
// webpack.config.js - minimal setup
480
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
481
482
module.exports = {
483
module: {
484
rules: [{
485
use: 'babel-loader',
486
test: /\.js$/,
487
exclude: /node_modules/,
488
options: {
489
plugins: ['lodash'],
490
presets: [['env', { modules: false }]]
491
}
492
}]
493
},
494
plugins: [
495
new LodashModuleReplacementPlugin(),
496
// ... other plugins
497
]
498
};
499
```
500
501
### Advanced Configuration
502
503
```javascript
504
// webpack.config.js - with selective features
505
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
506
507
module.exports = {
508
plugins: [
509
new LodashModuleReplacementPlugin({
510
// Enable collections support for object iteration
511
'collections': true,
512
// Enable path support for deep property access
513
'paths': true,
514
// Enable shorthands for property/matches shortcuts
515
'shorthands': true,
516
// Keep cloning disabled for smaller bundles (default: false)
517
'cloning': false
518
})
519
]
520
};
521
```
522
523
### Accessing Named Exports
524
525
```javascript
526
// Using exported data objects
527
const { features, overrides, stubs } = require('lodash-webpack-plugin');
528
529
// Check available features
530
console.log('Available features:', Object.keys(features));
531
532
// Check method overrides
533
console.log('Methods with automatic overrides:', Object.keys(overrides));
534
535
// Check stub functions
536
console.log('Available stubs:', stubs);
537
538
// Create plugin with dynamic feature detection
539
const enabledFeatures = {};
540
if (needsCloning) enabledFeatures.cloning = true;
541
if (needsPaths) enabledFeatures.paths = true;
542
543
const plugin = new LodashModuleReplacementPlugin(enabledFeatures);
544
545
// Access plugin state after compilation
546
console.log('Replaced modules:', plugin.matches);
547
```
548
549
### Rollup Integration
550
551
```javascript
552
// rollup.config.js
553
import Plugin from 'lodash-webpack-plugin';
554
import nodeResolve from '@rollup/plugin-node-resolve';
555
556
export default {
557
plugins: [
558
Plugin(nodeResolve(), {
559
'collections': true,
560
'paths': true
561
})
562
]
563
};
564
```
565
566
## Important Notes
567
568
- **Feature Dependencies**: Some features require others (e.g., `metadata` requires `currying`, `placeholders` requires `currying`)
569
- **Method Overrides**: Specific lodash methods automatically enable required features regardless of global settings
570
- **Bundle Size Impact**: Disabling more features results in smaller bundles but may cause unexpected behavior
571
- **Testing Recommended**: Always test functionality after configuring the plugin to ensure expected behavior
572
- **Compatibility**: Works with webpack 2+ and rollup, requires lodash as a dependency
573
- **Named Exports**: The plugin exports `features`, `overrides`, and `stubs` objects for external inspection
574
- **Plugin State**: Access the `matches` property after compilation to see which modules were replaced
575
- **Dual Mode**: The default export function works as both constructor (webpack) and factory function (rollup)