serverless
Version:
Serverless Framework - Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more
202 lines (145 loc) • 4.89 kB
Markdown
<!--
title: Serverless Framework - Creating plugins
menuText: Creating plugins
menuOrder: 1
description: How to create custom plugins to customize the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/guides/plugins/creating-plugins)
<!-- DOCS-SITE-LINK:END -->
# Creating custom plugins
Creating a custom plugin lets you:
- [Hook into _lifecycle events_ to add new logic](#lifecycle-events)
- [Define new CLI commands](custom-commands.md)
- [Define new variable sources](custom-variables.md)
- [Extend the `serverless.yml` syntax](custom-configuration.md)
- [Write extra information to the CLI output](cli-output.md)
- Add support for new cloud providers
## Creating a plugin
The simplest way to create a Serverless Framework plugin is to write a JavaScript file:
```javascript
'use strict';
class MyPlugin {
constructor() {
// The plugin is loaded
}
}
module.exports = MyPlugin;
```
The plugin can then be loaded in `serverless.yml` via a local path:
```yaml
# serverless.yml
service: app
functions:
# ...
plugins:
- ./my-plugin.js
```
### Distributing a plugin via NPM
Plugins can also be published to NPM and later installed in separate projects.
To correctly configure the plugin's NPM package, set the `main` property to point to your plugin file in `package.json`:
```json
{
"main": "my-plugin.js"
}
```
It is also a good practice to add `serverless` to the `peerDependencies` section. That ensures that your plugin runs only with the Serverless Framework versions it supports.
```json
{
...
"peerDependencies": {
"serverless": "^2.60 || 3"
}
}
```
Once the plugin is published on NPM, follow the documentation on [Installing plugins](README.md) to use the custom plugin.
## Lifecycle events
Lifecycle events are events that fire sequentially during a CLI command.
Additionally, for each event an additional `before` and `after` event is created. For example:
- `before:package:package`
- `package:package`
- `after:package:package`
- `before:deploy:deploy`
- `deploy:deploy`
- `after:deploy:deploy`
The `initialize` event is shared across all CLI commands and runs when the CLI starts.
Plugins can "hook" into existing lifecycle events to add behavior to commands like `deploy`, `package`, etc. via the `hooks` helper:
```javascript
'use strict';
class MyPlugin {
constructor() {
this.hooks = {
'initialize': () => this.init(),
'before:deploy:deploy': () => this.beforeDeploy(),
'after:deploy:deploy': () => this.afterDeploy(),
};
}
init() {
// Initialization
}
beforeDeploy() {
// Before deploy
}
afterDeploy() {
// After deploy
}
}
module.exports = MyPlugin;
```
Plugins can also create their own commands (with their own lifecycle events): read the [Custom commands documentation](custom-commands.md).
## Serverless instance
The `serverless` parameter provides access to the service configuration at runtime:
```javascript
'use strict';
class MyPlugin {
constructor(serverless) {
this.serverless = serverless;
this.hooks = {
initialize: () => this.init(),
};
}
init() {
console.log('Serverless instance: ', this.serverless);
// `serverless.service` contains the (resolved) serverless.yml config
const service = this.serverless.service;
console.log('Provider name: ', service.provider.name);
console.log('Functions: ', service.functions);
}
}
module.exports = MyPlugin;
```
**Note:** configuration values are only resolved _after_ plugins are initialized. Do not try to read configuration in the plugin constructor, as variables aren't resolved yet. Read configuration in lifecycle events only.
## CLI options
The `options` parameter provides access to the CLI options provided to the command:
```javascript
class MyPlugin {
constructor(serverless, options) {
// Log if a --verbose option was passed:
console.log(options.verbose);
}
}
```
## Provider-specific plugins
Plugins can be provider specific, which means that run only with a specific provider.
**Note:** Binding a plugin to a provider is optional. Serverless will always consider your plugin if you don't specify a `provider`.
To bind to a specific provider, retrieve it and set the `this.provider` property in the plugin constructor:
```javascript
class MyPlugin {
constructor(serverless, options) {
// bind to a specific provider
this.provider = serverless.getProvider('providerX');
// ...
}
}
```
The plugin will now only be executed when the service's provider matches the given provider.
## ESM plugins
If you use Node.js v12.22 or later, ESM plugins are also supported.
```javascript
export default class MyPlugin {
constructor() {
// The plugin is loaded
}
}
```