0
# Module Packaging
1
2
External module detection, dependency resolution, and packaging system supporting npm and yarn with workspace and monorepo support.
3
4
## Capabilities
5
6
### Module Inclusion Configuration
7
8
Configure how external modules are detected, included, and packaged in the deployment artifact.
9
10
```yaml { .api }
11
# Boolean format for simple inclusion
12
includeModules: boolean
13
14
# Object format for advanced configuration
15
includeModules:
16
packagePath: string # Relative path to package.json (default: './package.json')
17
nodeModulesRelativeDir: string # Relative path to node_modules directory
18
packageLockPath: string # Path to package-lock.json for NPM 8+ support
19
forceExclude: string[] # Modules to force exclude from packaging
20
forceInclude: string[] # Modules to force include in packaging
21
```
22
23
**Usage Examples:**
24
25
```yaml
26
# Simple inclusion - includes all external dependencies
27
custom:
28
webpack:
29
includeModules: true
30
31
# Advanced configuration
32
custom:
33
webpack:
34
includeModules:
35
packagePath: '../package.json' # Monorepo package.json location
36
nodeModulesRelativeDir: '../../' # Shared node_modules directory
37
packageLockPath: '../../package-lock.json' # Lock file for NPM 8+
38
forceExclude:
39
- 'aws-sdk' # Available in Lambda runtime
40
- 'optional-dev-dependency'
41
forceInclude:
42
- 'peer-dependency' # Include peer dependencies
43
- 'optional-runtime-dependency'
44
```
45
46
### External Module Detection
47
48
Automatic detection of external modules used by webpack bundles.
49
50
```javascript { .api }
51
/**
52
* External module detection and analysis
53
*/
54
interface ExternalModule {
55
name: string; // Module name (e.g., 'lodash', '@aws-sdk/client-s3')
56
version: string; // Version from package.json
57
dependencies: string[]; // Module's own dependencies
58
peerDependencies: string[]; // Required peer dependencies
59
optional: boolean; // Whether module is optional
60
builtin: boolean; // Whether module is Node.js builtin
61
}
62
63
/**
64
* Module detection process
65
*/
66
function detectExternalModules(compilation: any): ExternalModule[];
67
```
68
69
The plugin automatically scans webpack compilation results to identify external modules that need to be included in the deployment package.
70
71
**Usage Examples:**
72
73
```javascript
74
// webpack.config.js - Configure externals for detection
75
const nodeExternals = require('webpack-node-externals');
76
77
module.exports = {
78
entry: slsw.lib.entries,
79
target: 'node',
80
externals: [
81
nodeExternals({
82
// Modules to exclude from bundling but include in package
83
allowlist: ['some-module-to-bundle']
84
})
85
]
86
};
87
```
88
89
### Packager Integration
90
91
Support for multiple package managers with specific configuration options.
92
93
```yaml { .api }
94
# Package manager selection
95
packager: 'npm' | 'yarn'
96
97
# Packager-specific options
98
packagerOptions:
99
scripts: string[] # Additional scripts to run after install
100
noInstall: boolean # Skip install step (default: false)
101
ignoreLockfile: boolean # Ignore lock file during install
102
production: boolean # Install only production dependencies (default: true)
103
[customOption: string]: any # Additional packager-specific options
104
```
105
106
**Usage Examples:**
107
108
```yaml
109
# NPM configuration
110
custom:
111
webpack:
112
packager: 'npm'
113
packagerOptions:
114
scripts:
115
- 'rebuild' # Rebuild native modules
116
- 'prepare:lambda' # Custom preparation script
117
production: true
118
119
# Yarn configuration
120
custom:
121
webpack:
122
packager: 'yarn'
123
packagerOptions:
124
ignoreLockfile: false
125
scripts:
126
- 'postinstall'
127
production: true
128
```
129
130
### NPM Packager Implementation
131
132
NPM-specific packaging functionality with support for package-lock.json and npm workspaces.
133
134
```javascript { .api }
135
/**
136
* NPM packager interface implementation
137
*/
138
class NpmPackager {
139
static lockfileName: 'package-lock.json';
140
static mustCopyModules: false;
141
142
/**
143
* Get NPM version information
144
*/
145
static getPackagerVersion(cwd: string): Promise<{version: string}>;
146
147
/**
148
* Get production dependencies with specified depth
149
*/
150
static getProdDependencies(cwd: string, depth?: number): Promise<object>;
151
152
/**
153
* Install dependencies in specified directory
154
*/
155
static install(cwd: string, options?: object): Promise<void>;
156
157
/**
158
* Remove development dependencies
159
*/
160
static prune(cwd: string, options?: object): Promise<void>;
161
162
/**
163
* Run package scripts
164
*/
165
static runScripts(cwd: string, scriptNames: string[]): Promise<void>;
166
167
/**
168
* Rebase package-lock.json paths for relocated packages
169
*/
170
static rebaseLockfile(pathToPackageRoot: string, lockfile: object): void;
171
}
172
```
173
174
### Yarn Packager Implementation
175
176
Yarn-specific packaging functionality with workspace and monorepo support.
177
178
```javascript { .api }
179
/**
180
* Yarn packager interface implementation
181
*/
182
class YarnPackager {
183
static lockfileName: 'yarn.lock';
184
static mustCopyModules: true;
185
186
/**
187
* Get Yarn version information
188
*/
189
static getPackagerVersion(cwd: string): Promise<{version: string}>;
190
191
/**
192
* Get production dependencies from yarn.lock
193
*/
194
static getProdDependencies(cwd: string, depth?: number): Promise<object>;
195
196
/**
197
* Install dependencies using yarn
198
*/
199
static install(cwd: string, options?: object): Promise<void>;
200
201
/**
202
* Remove development dependencies
203
*/
204
static prune(cwd: string, options?: object): Promise<void>;
205
206
/**
207
* Run yarn scripts
208
*/
209
static runScripts(cwd: string, scriptNames: string[]): Promise<void>;
210
211
/**
212
* Rebase yarn.lock paths for relocated packages
213
*/
214
static rebaseLockfile(pathToPackageRoot: string, lockfile: object): void;
215
}
216
```
217
218
### Workspace and Monorepo Support
219
220
Configuration for monorepo and workspace environments with shared dependencies.
221
222
```yaml { .api }
223
# Monorepo configuration
224
custom:
225
webpack:
226
includeModules:
227
packagePath: '../package.json' # Workspace root package.json
228
nodeModulesRelativeDir: '../../' # Shared node_modules location
229
packageLockPath: '../../package-lock.json' # Root lock file location
230
```
231
232
**Usage Examples:**
233
234
```yaml
235
# Yarn workspace configuration
236
custom:
237
webpack:
238
packager: 'yarn'
239
includeModules:
240
packagePath: '../../package.json' # Workspace root
241
nodeModulesRelativeDir: '../../' # Shared node_modules
242
243
# NPM workspace configuration
244
custom:
245
webpack:
246
packager: 'npm'
247
includeModules:
248
packagePath: '../package.json'
249
nodeModulesRelativeDir: '../'
250
packageLockPath: '../package-lock.json'
251
```
252
253
For a typical monorepo structure:
254
```
255
workspace-root/
256
├── package.json
257
├── node_modules/
258
├── packages/
259
│ ├── service-a/
260
│ │ ├── package.json
261
│ │ └── serverless.yml
262
│ └── service-b/
263
│ ├── package.json
264
│ └── serverless.yml
265
```
266
267
### Dependency Resolution Process
268
269
Multi-step process for resolving and packaging external dependencies.
270
271
```javascript { .api }
272
/**
273
* Dependency resolution process steps
274
*/
275
const resolutionSteps = [
276
'detectExternalModules', // Scan webpack output for external references
277
'analyzeDependencies', // Analyze package.json dependencies
278
'resolvePeerDependencies', // Include required peer dependencies
279
'applyForceIncludeExclude', // Apply force include/exclude rules
280
'generatePackageJson', // Create deployment package.json
281
'installDependencies', // Install using selected packager
282
'runPostInstallScripts', // Execute post-install scripts
283
'pruneDevDependencies', // Remove development dependencies
284
'copyToDeploymentPackage' // Copy to final deployment artifact
285
];
286
287
/**
288
* Dependency tree structure
289
*/
290
interface DependencyTree {
291
[moduleName: string]: {
292
version: string;
293
dependencies?: DependencyTree;
294
peerDependencies?: string[];
295
optional?: boolean;
296
};
297
}
298
```
299
300
### Force Include and Exclude Rules
301
302
Fine-grained control over which modules are included or excluded from packaging.
303
304
```yaml { .api }
305
# Force inclusion and exclusion configuration
306
includeModules:
307
forceExclude: string[] # Modules to always exclude
308
forceInclude: string[] # Modules to always include
309
```
310
311
**Usage Examples:**
312
313
```yaml
314
custom:
315
webpack:
316
includeModules:
317
forceExclude:
318
- 'aws-sdk' # Available in Lambda runtime
319
- 'serverless-webpack' # Build-time only dependency
320
- '@types/*' # TypeScript type definitions
321
- 'devDependency' # Development-only modules
322
forceInclude:
323
- 'optional-dependency' # Optional deps not auto-detected
324
- 'peer-dependency' # Peer deps when not installed
325
- 'native-module' # Native modules needing rebuild
326
```
327
328
Common exclusion patterns:
329
- **aws-sdk**: Available in AWS Lambda runtime environment
330
- **serverless-webpack**: Build tool, not needed at runtime
331
- **@types/**: TypeScript definitions, compiled away
332
- **webpack**: Build tool dependencies
333
334
Common inclusion patterns:
335
- **peer-dependencies**: When not automatically installed
336
- **optional-dependencies**: Runtime-optional but required modules
337
- **native-modules**: Binary modules needing platform-specific builds
338
339
### Package.json Generation
340
341
Automatic generation of deployment package.json with resolved dependencies.
342
343
```javascript { .api }
344
/**
345
* Generated package.json structure for deployment
346
*/
347
interface DeploymentPackageJson {
348
name: string; // Service name
349
version: string; // Service version
350
description?: string; // Service description
351
main?: string; // Entry point (usually not needed)
352
dependencies: { // Production dependencies only
353
[name: string]: string; // Module name and version
354
};
355
scripts?: { // Post-install scripts if configured
356
[name: string]: string;
357
};
358
}
359
```
360
361
The plugin generates a minimal package.json containing only:
362
- Production dependencies actually used by the code
363
- Resolved versions from original package.json/lock files
364
- Optional post-install scripts if configured
365
366
### Native Module Handling
367
368
Special handling for native modules requiring compilation for the Lambda environment.
369
370
```javascript { .api }
371
/**
372
* Native module detection and handling
373
*/
374
interface NativeModuleConfig {
375
rebuildCommand: string; // Command to rebuild native modules
376
targetPlatform: string; // Target platform (e.g., 'linux')
377
targetArch: string; // Target architecture (e.g., 'x64')
378
dockerImage?: string; // Docker image for cross-compilation
379
}
380
```
381
382
**Usage Examples:**
383
384
```yaml
385
# Native module rebuilding
386
custom:
387
webpack:
388
packager: 'npm'
389
packagerOptions:
390
scripts:
391
- 'rebuild' # npm rebuild for native modules
392
393
# Yarn native module handling
394
custom:
395
webpack:
396
packager: 'yarn'
397
packagerOptions:
398
scripts:
399
- 'install --force' # Force reinstall native modules
400
```
401
402
### Performance Optimization
403
404
Optimization techniques for faster packaging and smaller deployment artifacts.
405
406
```javascript { .api }
407
/**
408
* Packaging performance optimization options
409
*/
410
interface PackagingOptimizations {
411
concurrency: number; // Parallel packaging operations
412
skipDuplicates: boolean; // Skip duplicate dependency resolution
413
cacheEnabled: boolean; // Enable packaging cache
414
symlinkHandling: 'preserve' | 'resolve' | 'ignore'; // Symlink handling strategy
415
}
416
```
417
418
**Usage Examples:**
419
420
```yaml
421
custom:
422
webpack:
423
concurrency: 4 # Limit concurrent operations
424
includeModules:
425
forceExclude:
426
- 'unused-*' # Exclude unused module patterns
427
```
428
429
### Packaging Validation
430
431
Validation and verification of packaged dependencies.
432
433
```javascript { .api }
434
/**
435
* Package validation and verification
436
*/
437
interface PackageValidation {
438
validatePackageIntegrity: boolean; // Verify package contents
439
checkMissingDependencies: boolean; // Check for missing runtime deps
440
validateNativeModules: boolean; // Verify native module compatibility
441
reportPackageSize: boolean; // Report final package size
442
}
443
```
444
445
The plugin automatically validates:
446
- All detected external modules are properly packaged
447
- No missing dependencies that would cause runtime errors
448
- Native modules are compiled for the correct platform
449
- Package size warnings for large deployments
450
451
### Troubleshooting Common Issues
452
453
Common module packaging issues and solutions.
454
455
```javascript { .api }
456
/**
457
* Common packaging issues and diagnostics
458
*/
459
interface PackagingDiagnostics {
460
missingModules: string[]; // Modules referenced but not found
461
circularDependencies: string[]; // Circular dependency warnings
462
oversizedPackages: string[]; // Packages exceeding size limits
463
nativeModuleIssues: string[]; // Native module compilation issues
464
}
465
```
466
467
**Common Solutions:**
468
469
```yaml
470
# Missing peer dependencies
471
custom:
472
webpack:
473
includeModules:
474
forceInclude:
475
- 'missing-peer-dep'
476
477
# Circular dependency resolution
478
custom:
479
webpack:
480
includeModules:
481
forceExclude:
482
- 'problematic-module'
483
484
# Large package optimization
485
custom:
486
webpack:
487
includeModules:
488
forceExclude:
489
- 'large-unused-module'
490
- 'development-only-module'
491
```
492
493
Debug packaging issues:
494
```bash
495
# Enable debug output
496
export SLS_DEBUG=*
497
sls package
498
499
# Inspect .webpack directory contents
500
sls webpack --out debug-build
501
ls -la debug-build/
502
```