serverless-esbuild
Advanced tools
Comparing version
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.providerRuntimeMatcher = exports.doSharePath = exports.getDepsFromBundle = exports.flatDep = exports.extractFileNames = void 0; | ||
exports.buildServerlessV3LoggerFromLegacyLogger = exports.providerRuntimeMatcher = exports.doSharePath = exports.getDepsFromBundle = exports.flatDep = exports.extractFileNames = void 0; | ||
const fs_extra_1 = __importDefault(require("fs-extra")); | ||
@@ -131,1 +131,11 @@ const path_1 = __importDefault(require("path")); | ||
}); | ||
const buildServerlessV3LoggerFromLegacyLogger = (legacyLogger, verbose) => ({ | ||
error: legacyLogger, | ||
warning: legacyLogger, | ||
notice: legacyLogger, | ||
info: legacyLogger, | ||
debug: verbose ? legacyLogger : () => null, | ||
verbose: legacyLogger, | ||
success: legacyLogger, | ||
}); | ||
exports.buildServerlessV3LoggerFromLegacyLogger = buildServerlessV3LoggerFromLegacyLogger; |
@@ -36,3 +36,3 @@ "use strict"; | ||
class EsbuildServerlessPlugin { | ||
constructor(serverless, options) { | ||
constructor(serverless, options, logging) { | ||
this.getCachedOptions = (0, ramda_1.memoizeWith)((0, ramda_1.always)('cache'), () => { | ||
@@ -51,2 +51,5 @@ var _a, _b; | ||
this.options = options; | ||
this.log = | ||
(logging === null || logging === void 0 ? void 0 : logging.log) || | ||
(0, helper_1.buildServerlessV3LoggerFromLegacyLogger)(this.serverless.cli.log, this.options.verbose); | ||
this.packExternalModules = pack_externals_1.packExternalModules.bind(this); | ||
@@ -164,4 +167,4 @@ this.pack = pack_1.pack.bind(this); | ||
chokidar_1.default.watch(this.buildOptions.watch.pattern, options).on('all', () => this.bundle(true) | ||
.then(() => this.serverless.cli.log('Watching files for changes...')) | ||
.catch(() => this.serverless.cli.log('Bundle error, waiting for a file change to reload...'))); | ||
.then(() => this.log.verbose('Watching files for changes...')) | ||
.catch(() => this.log.error('Bundle error, waiting for a file change to reload...'))); | ||
} | ||
@@ -200,3 +203,3 @@ prepare() { | ||
this.prepare(); | ||
this.serverless.cli.log(`Compiling to ${this.buildOptions.target} bundle with esbuild...`); | ||
this.log.verbose(`Compiling to ${this.buildOptions.target} bundle with esbuild...`); | ||
if (this.buildOptions.disableIncremental === true) { | ||
@@ -245,7 +248,7 @@ incremental = false; | ||
}; | ||
this.serverless.cli.log(`Compiling with concurrency: ${(_a = this.buildOptions.concurrency) !== null && _a !== void 0 ? _a : 'Infinity'}`); | ||
this.log.verbose(`Compiling with concurrency: ${(_a = this.buildOptions.concurrency) !== null && _a !== void 0 ? _a : 'Infinity'}`); | ||
this.buildResults = await (0, p_map_1.default)(this.rootFileNames, bundleMapper, { | ||
concurrency: this.buildOptions.concurrency, | ||
}); | ||
this.serverless.cli.log('Compiling completed.'); | ||
this.log.verbose('Compiling completed.'); | ||
return this.buildResults.map((r) => r.result); | ||
@@ -252,0 +255,0 @@ } |
@@ -72,4 +72,3 @@ "use strict"; | ||
!packageJson.devDependencies[externalModule.external]) { | ||
this.options.verbose && | ||
this.serverless.cli.log(`INFO: Runtime dependency '${externalModule.external}' not found in dependencies or devDependencies. It has been excluded automatically.`); | ||
this.log.debug(`INFO: Runtime dependency '${externalModule.external}' not found in dependencies or devDependencies. It has been excluded automatically.`); | ||
return; | ||
@@ -85,7 +84,6 @@ } | ||
// Runtime dependency found in devDependencies but not forcefully excluded | ||
this.serverless.cli.log(`ERROR: Runtime dependency '${externalModule.external}' found in devDependencies.`); | ||
this.log.error(`ERROR: Runtime dependency '${externalModule.external}' found in devDependencies.`); | ||
throw new this.serverless.classes.Error(`Serverless-webpack dependency error: ${externalModule.external}.`); | ||
} | ||
this.options.verbose && | ||
this.serverless.cli.log(`INFO: Runtime dependency '${externalModule.external}' found in devDependencies. It has been excluded automatically.`); | ||
this.log.debug(`INFO: Runtime dependency '${externalModule.external}' found in devDependencies. It has been excluded automatically.`); | ||
return; | ||
@@ -117,4 +115,3 @@ } | ||
if (!(0, ramda_1.isEmpty)(peerDependenciesWithoutOptionals)) { | ||
this.options.verbose && | ||
this.serverless.cli.log(`Adding explicit non-optionals peers for dependency ${externalModule.external}`); | ||
this.log.debug(`Adding explicit non-optionals peers for dependency ${externalModule.external}`); | ||
const peerModules = getProdModules.call(this, (0, ramda_1.compose)((0, ramda_1.map)(([external]) => ({ external })), ramda_1.toPairs)(peerDependenciesWithoutOptionals), packageJsonPath, rootPackageJsonPath); | ||
@@ -125,3 +122,3 @@ Array.prototype.push.apply(prodModules, peerModules); | ||
catch (e) { | ||
this.serverless.cli.log(`WARNING: Could not check for peer dependencies of ${externalModule.external}`); | ||
this.log.warning(`WARNING: Could not check for peer dependencies of ${externalModule.external}`); | ||
} | ||
@@ -191,7 +188,6 @@ }, externalModules); | ||
if (!(0, ramda_1.isEmpty)(packageSections)) { | ||
this.options.verbose && | ||
this.serverless.cli.log(`Using package.json sections ${(0, ramda_1.join)(', ', (0, ramda_1.keys)(packageSections))}`); | ||
this.log.debug(`Using package.json sections ${(0, ramda_1.join)(', ', (0, ramda_1.keys)(packageSections))}`); | ||
} | ||
// Get first level dependency graph | ||
this.options.verbose && this.serverless.cli.log(`Fetch dependency graph from ${packageJson}`); | ||
this.log.debug(`Fetch dependency graph from ${packageJson}`); | ||
// (1) Generate dependency composition | ||
@@ -202,3 +198,3 @@ const externalModules = (0, ramda_1.map)((external) => ({ external }), externals); | ||
// The compiled code does not reference any external modules at all | ||
this.serverless.cli.log('No external modules needed'); | ||
this.log.warning('No external modules needed'); | ||
return; | ||
@@ -224,3 +220,3 @@ } | ||
if (exists) { | ||
this.serverless.cli.log('Package lock found - Using locked versions'); | ||
this.log.verbose('Package lock found - Using locked versions'); | ||
try { | ||
@@ -235,3 +231,3 @@ let packageLockFile = this.serverless.utils.readFileSync(packageLockPath); | ||
catch (err) { | ||
this.serverless.cli.log(`Warning: Could not read lock file: ${err.message}`); | ||
this.log.warning(`Warning: Could not read lock file: ${err.message}`); | ||
} | ||
@@ -245,11 +241,10 @@ } | ||
const start = Date.now(); | ||
this.serverless.cli.log('Packing external modules: ' + compositeModules.join(', ')); | ||
this.log.verbose('Packing external modules: ' + compositeModules.join(', ')); | ||
const installExtraArgs = this.buildOptions.installExtraArgs; | ||
await packager.install(compositeModulePath, installExtraArgs, exists); | ||
this.options.verbose && this.serverless.cli.log(`Package took [${Date.now() - start} ms]`); | ||
this.log.debug(`Package took [${Date.now() - start} ms]`); | ||
// Prune extraneous packages - removes not needed ones | ||
const startPrune = Date.now(); | ||
await packager.prune(compositeModulePath); | ||
this.options.verbose && | ||
this.serverless.cli.log(`Prune: ${compositeModulePath} [${Date.now() - startPrune} ms]`); | ||
this.log.debug(`Prune: ${compositeModulePath} [${Date.now() - startPrune} ms]`); | ||
// Run packager scripts | ||
@@ -259,6 +254,5 @@ if (Object.keys(packagerScripts).length > 0) { | ||
await packager.runScripts(this.buildDirPath, Object.keys(packagerScripts)); | ||
this.options.verbose && | ||
this.serverless.cli.log(`Packager scripts took [${Date.now() - startScripts} ms].\nExecuted scripts: ${Object.values(packagerScripts).map((script) => `\n ${script}`)}`); | ||
this.log.debug(`Packager scripts took [${Date.now() - startScripts} ms].\nExecuted scripts: ${Object.values(packagerScripts).map((script) => `\n ${script}`)}`); | ||
} | ||
} | ||
exports.packExternalModules = packExternalModules; |
@@ -41,3 +41,3 @@ "use strict"; | ||
func.package = Object.assign({}, func.package, { disable: true }); | ||
this.serverless.cli.log(`${func.name} is packaged by the esbuild plugin. Ignore messages from SLS.`); | ||
this.log.verbose(`${func.name} is packaged by the esbuild plugin. Ignore messages from SLS.`); | ||
} | ||
@@ -108,3 +108,3 @@ else { | ||
const { size } = fs_extra_1.default.statSync(artifactPath); | ||
this.serverless.cli.log(`Zip service ${this.serverless.service.service} - ${(0, utils_1.humanSize)(size)} [${Date.now() - startZip} ms]`); | ||
this.log.verbose(`Zip service ${this.serverless.service.service} - ${(0, utils_1.humanSize)(size)} [${Date.now() - startZip} ms]`); | ||
// defined present zip as output artifact | ||
@@ -164,3 +164,3 @@ this.serverless.service.package.artifact = artifactPath; | ||
const { size } = fs_extra_1.default.statSync(artifactPath); | ||
this.serverless.cli.log(`Zip function: ${functionAlias} - ${(0, utils_1.humanSize)(size)} [${Date.now() - startZip} ms]`); | ||
this.log.verbose(`Zip function: ${functionAlias} - ${(0, utils_1.humanSize)(size)} [${Date.now() - startZip} ms]`); | ||
// defined present zip as output artifact | ||
@@ -167,0 +167,0 @@ setFunctionArtifactPath.call(this, func, path_1.default.relative(this.serviceDirPath, artifactPath)); |
@@ -39,3 +39,3 @@ "use strict"; | ||
const message = `Could not find packager '${packagerId}'`; | ||
this.serverless.cli.log(`ERROR: ${message}`); | ||
this.log.error(`ERROR: ${message}`); | ||
throw new this.serverless.classes.Error(message); | ||
@@ -42,0 +42,0 @@ } |
{ | ||
"name": "serverless-esbuild", | ||
"description": "Serverless plugin for zero-config JavaScript and TypeScript code bundling using extremely fast esbuild", | ||
"version": "1.25.0", | ||
"version": "1.26.0", | ||
"license": "MIT", | ||
@@ -52,3 +52,3 @@ "author": "Victor Korzunin", | ||
"@types/semver": "^7.3.8", | ||
"@types/serverless": "^1.78.25", | ||
"@types/serverless": "^3.0.1", | ||
"@typescript-eslint/eslint-plugin": "^4.2.0", | ||
@@ -55,0 +55,0 @@ "@typescript-eslint/parser": "^4.2.0", |
217
README.md
@@ -13,10 +13,29 @@ # 💨 serverless-esbuild | ||
- Zero-config: Works out of the box without the need to install any other compiler or plugins | ||
- Supports ESNext syntax with transforming limitations (See _Note_) | ||
- Supports `sls package`, `sls deploy` and `sls deploy function` | ||
- Supports `sls invoke local` | ||
- Integrates nicely with [`serverless-offline`](https://github.com/dherault/serverless-offline) | ||
- Zero-config: Works out of the box without the need to install any additional plugins | ||
- Works with Typescript and Javascript projects | ||
- Supports `sls package`, `sls deploy`, `sls deploy function` | ||
- Integrates with [`Serverless Invoke Local`](https://www.serverless.com/framework/docs/providers/aws/cli-reference/invoke-local) & [`serverless-offline`](https://github.com/dherault/serverless-offline) | ||
_Note_: The default JavaScript syntax target is determined from serverless provider configuration otherwise set to [`node12`], so the final bundle will be supported by all [AWS Lambda Node.js runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). If you still using an old lambda runtime and have to respect it you can play with esbuild `target` option, see [JavaScript syntax support](https://github.com/evanw/esbuild#javascript-syntax-support) for more details about syntax transform limitations. | ||
## Table of Contents | ||
- [Install](#install) | ||
- [Configuration](#configuration) | ||
- [Examples](#examples) | ||
- [Options](#options) | ||
- [Default Esbuild Options](#default-esbuild-options) | ||
- [Packager Options](#packager-options) | ||
- [Watch Options](#watch-options) | ||
- [Supported Runtimes](#supported-runtimes) | ||
- [Advanced Configuration](#advanced-configuration) | ||
- [Including Extra Files](#including-extra-files) | ||
- [External Dependencies](#external-dependencies) | ||
- [Esbuild Plugins](#esbuild-plugins) | ||
- [Usage](#usage) | ||
- [Automatic Compilation](#automatic-compilation) | ||
- [Serverless Offline](#serverless-offline) | ||
- [Serverless Dynamodb Local](#serverless-dynamodb-local) | ||
- [Invoke Local](#invoke-local) | ||
- [External Tools](#external-tools) | ||
- [Contributors](#contributors) | ||
## Install | ||
@@ -40,5 +59,5 @@ | ||
## Configure | ||
## Configuration | ||
By default, no configuration is required, but you can change esbuild behavior in custom `esbuild` section in `serverless.yaml` config: | ||
By default, no configuration is required, but you can override the default behavior via the `custom.esbuild` section in the `serverless.yml` file. | ||
@@ -52,16 +71,70 @@ ```yml | ||
Check [esbuild](https://github.com/evanw/esbuild#command-line-usage) documentation for the full list of available options. Note that some options like `entryPoints` or `outdir` cannot be overwritten. We rely on the Javascript API so make sure you provide the JavaScript options as they can be different to the CLI options. | ||
The package specified in the `exclude` option is passed to esbuild as `external`, but it is not included in the function bundle either. The default value for this option is `['aws-sdk']`. You can set `exclude` to `*` to disable packaging `node_modules`. | ||
### Examples | ||
See [example folder](examples) for a minimal example. | ||
See [example folder](examples) for some example configurations. | ||
### Including extra files | ||
### Options | ||
All files from `package/patterns` will be included in the final build file. See [Patterns](https://serverless.com/framework/docs/providers/aws/guide/packaging#patterns). | ||
| Option | Description | Default | | ||
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | | ||
| Esbuild Options | This plugin can take almost any [Esbuild Javascript Build Option](https://esbuild.github.io/api/#build-api). See [Default Esbuild Options](#default-esbuild-options) | N/A | | ||
| `concurrency` | The number of concurrent zip and bundle operations to run at once (This can be memory intensive). eg. `10`. _NOTE_: This will produce slower builds. | `'Infinity'` | | ||
| `disableIncremental` | Disables the use of esbuild `incremental` compilation. | `false` | | ||
| `exclude` | An array of dependencies to exclude from the Lambda. This is passed to the esbuild `external` option. Set to `*` to disable packaging `node_modules` | `['aws-sdk']` | | ||
| `installExtraArgs` | Optional arguments passed to npm or yarn for `external` dependency resolution. eg. `['--legacy-peer-deps']` for npm v7+ to use legacy `peerDependency` resolution behavior | `[]` | | ||
| `keepOutputDirectory` | Keeps the `.esbuild` output folder. Useful for debugging. | `false` | | ||
| `nativeZip` | Uses the system's `zip` executable to create archives. _NOTE_: This will produce non-deterministic archives which causes a Serverless deployment update on every deploy. | `false` | | ||
| `packagePath` | Path to the `package.json` file for `external` dependency resolution. | `'./package.json'` | | ||
| `packager` | Package to use for `external` dependency resolution. Values: `npm`, `yarn`, `pnpm` | `'npm'` | | ||
| `packagerOptions` | Extra options for packagers for `external` dependency resolution. See [Packager Options](#packager-options) | N/A | | ||
| `watch` | Watch options for `serverless-offline`. See [Watch Options](#watch-options) | N/A | | ||
Include/exclude is deprecated, but still supported. | ||
#### Default Esbuild Options | ||
The following `esbuild` options are automatically set. | ||
| Option | Default | Notes | | ||
| ------------- | ---------- | ---------------------------------------------------------------------- | | ||
| `bundle` | `true` | Esbuild requires this for use with `external` | | ||
| `entryPoints` | N/A | Cannot be overridden | | ||
| `incremental` | N/A | Cannot be overridden. Use `disableIncremental` to disable it | | ||
| `outDir` | N/A | Cannot be overridden | | ||
| `platform` | `'node'` | Set to `'neutral'` to enable ESM support | | ||
| `target` | `'node12'` | We dynamically set this. See [Supported Runtimes](#supported-runtimes) | | ||
#### Packager Options | ||
| Option | Description | Default | | ||
| --------- | ----------------------------------------------------------------------------------------------------- | ----------- | | ||
| `scripts` | A string or array of scripts to be executed, currently only supports 'scripts' for npm, pnpm and yarn | `undefined` | | ||
#### Watch Options | ||
| Option | Description | Default | | ||
| --------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | | ||
| `pattern` | An [anymatch-compatible definition](https://github.com/es128/anymatch) for the watcher to respond to | `./\*_/_.(js\|ts)` (watches all `.js` and `.ts` files) | | ||
| `ignore` | An [anymatch-compatible definition](https://github.com/es128/anymatch) for the watcher to ignore | `['.build', 'dist', 'node_modules', '.serverless']` | | ||
## Supported Runtimes | ||
This plugin will automatically set the esbuild `target` for the following supported Serverless runtimes | ||
AWS: | ||
| Runtime | Target | | ||
| ------------ | -------- | | ||
| `nodejs14.x` | `node14` | | ||
| `nodejs12.x` | `node12` | | ||
If you wish to use this plugin alongside non Node functions like Python or functions with images, this plugin will automatically ignore any function which does not contain a handler or use a supported Node.js runtime. | ||
## Advanced Configuration | ||
### Including Extra Files | ||
[Serverless Package Configuration](https://www.serverless.com/framework/docs/providers/aws/guide/packaging#package-configuration) will behave in the same way as native packaging. You can use `patterns`, `include` and `exclude` to include extra files into your bundles. | ||
### External Dependencies | ||
Packages that are marked as `external` and exist in the package.json's `dependencies` will be installed and included with your build under `node_modules`. You can configure how these are installed: | ||
Packages that are marked as `external` and exist in the package.json's `dependencies` will be installed and included with your build under `node_modules`. You can customize this with a number of options. | ||
@@ -71,8 +144,12 @@ ```yml | ||
esbuild: | ||
packager: yarn # optional - npm, pnpm or yarn, default is npm | ||
packagePath: absolute/path/to/package.json # optional - by default it looks for a package.json in the working directory | ||
packagerOptions: # optional - packager related options, currently supports only 'scripts' for both npm, pnpm and yarn | ||
scripts: # scripts to be executed, can be a string or array of strings | ||
external: | ||
- lodash | ||
packager: yarn | ||
packagePath: absolute/path/to/package.json | ||
packagerOptions: | ||
scripts: | ||
- echo 'Hello World!' | ||
- rm -rf node_modules | ||
installExtraArgs: | ||
- '--legacy-peer-deps' | ||
``` | ||
@@ -92,18 +169,6 @@ | ||
### Passing Extra Arguments to Packager | ||
### Esbuild Plugins | ||
This might be required to resolve some issues on package installation. | ||
One example is to pass `--legacy-peer-deps` to npm v7+, to use legacy `peerDependency` resolution behavior. | ||
_Note: The [Esbuild plugins API](https://esbuild.github.io/plugins/) is still experimental_ | ||
```yml | ||
custom: | ||
esbuild: | ||
installExtraArgs: # optional. Default is empty (no arguments) | ||
- '--legacy-peer-deps' | ||
``` | ||
### Using esbuild plugins | ||
_Note that the plugins API is still experimental : see [the documentation page](https://esbuild.github.io/plugins/)_ | ||
You can configure esbuild plugins by passing a plugins' configuration file: | ||
@@ -148,26 +213,2 @@ | ||
### Native Zip | ||
If you wish to use your system's `zip` executable to create archives (can be significantly faster when working with many large archives), set the `nativeZip` option: | ||
```yml | ||
custom: | ||
esbuild: | ||
nativeZip: true | ||
``` | ||
_NOTE_: This will produce non-deterministic archives which causes a Serverless deployment update on every deploy. | ||
### Concurrency | ||
If you wish to limit the concurrency of the bundling process (can be very expensive on memory), set the `concurrency` option: | ||
```yml | ||
custom: | ||
esbuild: | ||
concurrency: 10 | ||
``` | ||
_NOTE_: This will produce slower builds. | ||
## Usage | ||
@@ -177,24 +218,6 @@ | ||
The normal Serverless deploy procedure will automatically compile with `esbuild`: | ||
As long as the plugin is properly installed, all regular Serverless operations `sls package`, `sls deploy`, `sls deploy function`, `sls invoke local`, `sls offline` will automatically compile using `serverless-esbuild`. | ||
- Create the Serverless project with `serverless create -t aws-nodejs` | ||
- Install Serverless esbuild plugin as above | ||
- Deploy with `serverless deploy` | ||
### Serverless Offline | ||
### ESM Support | ||
If you wish to enable ESM support you may set the esbuild [platform](https://esbuild.github.io/api/#platform) option to `neutral`. This is set to `node` by default. | ||
### Usage with non Node functions | ||
If you wish to use this plugin alongside non Node functions like Python, this plugin will automatically ignore any function which does not contain a handler or use a supported Node.js runtime. | ||
Current supported runtimes: | ||
- AWS | ||
- nodejs14.x | ||
- nodejs12.x | ||
### Usage with serverless-offline | ||
The plugin integrates very well with [serverless-offline](https://github.com/dherault/serverless-offline) to | ||
@@ -218,12 +241,5 @@ simulate AWS Lambda and AWS API Gateway locally. | ||
Automatic compilation is available while using the plugin with `serverless-offline`. Following are the default configuration: | ||
Automatic compilation is available while using the plugin with `serverless-offline`. | ||
``` | ||
pattern: './**/*.(js|ts)' # watches all javascript or typescripts files in the project | ||
ignore: [.build, 'dist', 'node_modules', '.serverless'] | ||
``` | ||
You can override the defaults by using `watch` option in serverless esbuild config. Both options take [anymatch-compatible definition] (https://github.com/es128/anymatch) | ||
``` | ||
custom: | ||
@@ -236,5 +252,5 @@ esbuild: | ||
Note: When overriding ignore pattern, remember to ignore `.build` directory to avoid endless compilation. | ||
Note: When overriding the ignore pattern, remember to ignore `.build` directory to avoid endless compilation. | ||
#### serverless-dynamodb-local | ||
#### Serverless Dynamodb Local | ||
@@ -253,29 +269,8 @@ Configure your service the same as mentioned above, but additionally add the `serverless-dynamodb-local` | ||
### Run a function locally | ||
### Invoke Local | ||
To run your compiled functions locally you can: | ||
This plugin supports the Serverless [Invoke Local](https://www.serverless.com/framework/docs/providers/aws/cli-reference/invoke-local) functionality and will automatically compile the selected function. | ||
```bash | ||
$ serverless invoke local --function <function-name> | ||
``` | ||
## External Tools | ||
Options are: | ||
- `--function` or `-f` (required) is the name of the function to run | ||
- `--path` or `-p` (optional) path to JSON or YAML file holding input data | ||
- `--data` or `-d` (optional) input data | ||
## Plugin-Specific Options in Serverless Config | ||
These options belong under `custom.esbuild` in your `serverless.yml` or `serverless.ts` file, and are specific to this plugin (these are not esbuild API options): | ||
- `packager`: Package to use (npm, pnpm or yarn - npm is default) | ||
- `packagePath`: Path to the `package.json` file (`./package.json` is default) | ||
- `packagerOptions`: | ||
- `scripts`: A string or array of scripts to be executed, currently only supports 'scripts' for npm, pnpm and yarn | ||
- `exclude`: An array of dependencies to exclude (declares it as an external as well as excludes it from Lambda ZIP file) | ||
- `installExtraArgs`: Optional arguments passed to npm or yarn (empty is default) | ||
## External tools | ||
- [`serverless-analyze-bundle-plugin`](https://github.com/adriencaccia/serverless-analyze-bundle-plugin): a plugin that allow users to analyze the bundle of a lambda | ||
@@ -282,0 +277,0 @@ |
90090
2.95%1555
0.45%286
-1.72%