Как создать собственный плагин Serverless Framework для AWS Lambda с использованием JavaScript

Автор: | 11.08.2026

Фреймворк Serverless упрощает развертывание приложений в AWS Lambda. Однако в настоящее время Serverless не поддерживает бинарные файлы, но мы можем решить эту проблему, реализовав плагин Serverless и загрузив правильную конфигурацию в AWS API Gateway.

В этой статье мы:

— Настроим npm-проект и создадим приложение «Hello World» с красивым фоновым изображением

— Настроим фреймворк Serverless и развернем это приложение на AWS Lambda

— Научимся использовать AWS SDK, воссоздав плагин serverless для поддержки бинарных файлов в AWS API Gateway

— Опубликуем плагин в репозитории npm

Для выполнения задач в этой статье вам понадобятся:

— Аккаунт AWS

— Аккаунт npm

— Установленные Node.js и npm

— Установленный AWS CLI

# Настройка окружения и «Hello World!»

Создадим наше приложение. Настроим npm-проект и установим зависимости:

Создадим наше приложение:

Внутри `dist/app.js`:

мы будем:

— Инициализировать приложение express

— Устанавливать расширение представлений и каталог

— Добавлять отображение на главную страницу (‘/’)

Для этого вставьте этот код в файл `dist/app.js`:

Далее добавим наше представление. Вставьте этот код в файл `dist/views/index.html`:

Пришло время для некоторой стильной декорации с помощью CSS. Вставьте эти стили в файл `dist/assets/css/main.css`:

Как видите, мы используем изображение в качестве фона для нашего приложения. Вы можете получить его здесь и сохранить в каталоге `dist/assets/img` как `sandbox.gif`:

Оно стильное. Не правда ли?

Мы готовы поместить некоторый код в наш файл «localhost-entry», `local.js`:

Нам нужно только добавить соответствующие скрипты в файл `package.json`:

И мы можем запустить наше приложение на localhost:

Вы должны увидеть вывод этой команды:

Перейдя по указанному URL в браузере, вы должны увидеть:

Ок! Приложение готово. Теперь перейдем к развертыванию его на AWS Lambda. Нам нужно добавить два файла:

В `lambda.js` добавьте код для функции AWS Lambda:

В `serverless.yml` добавьте следующую конфигурацию:

Теперь нам нужно добавить только еще один скрипт в `package.json`:

И мы можем развернуть приложение:

Вывод этой команды должен быть:

Перейдя по предоставленному URL, вы можете увидеть ваше приложение, развернутое на AWS Lambda.

Но… эй… мое потрясающее фоновое изображение отсутствует!

Это связано с отсутствием поддержки бинарных файлов в нашем API Gateway, но мы можем решить это с помощью нашего плагина.

Если вы хотите наверстать этот шаг:

Мы можем использовать консоль AWS для решения проблемы вручную. После входа в консоль выберите «API Gateway» из меню «Services» в разделе «Application Services» и нажмите на ваш API (убедитесь, что вы находитесь в правильном регионе AWS):

Из левой панели навигации выберите `Binary support`:

Как видите, здесь нет ни одного типа. Добавим тип нашего изображения: нажмите кнопку `edit`, затем `add binary media type` введите `image/gif` и нажмите `save`:

После этого (и любого другого) изменения в API Gateway вам нужно будет переразвернуть его:

Какого черта?! Ладно, легко. В AWS API Gateway есть одна «маленькая» проблема. Обновите ваш запрос с заголовком `Accept` и значением `image/gif`. Взрыв! Теперь это работает:

Но… браузер не отправляет заголовок `Accept`. Что теперь? Есть обходной путь. Чтобы API Gateway отправлял бинарные файлы в ответ на каждый запрос (без ожидания заголовка `Accept`), вам нужно указать хотя бы один тип MIME как универсальный `*/*`. Вы можете узнать больше об этой проблеме здесь:

https://github.com/awslabs/serverless-application-model/issues/145#issuecomment-311672573

Как написано в проблеме, теперь все наши бинарные данные отправляются в кодировке base64, поэтому нам нужно декодировать их на стороне сервера. Измените файл `lambda.js` на:

Теперь наше приложение будет работать правильно. Разверните его снова (`npm run deploy`) и проверьте предоставленный URL.

git clone https://github.com/maciejtreder/serverless-apigw-binary.git

cd serverless-apigw-binary

git checkout tutorialSecondStep

npm install

npm run deploy

# Создание плагина Serverless

У нас готово и работает наше приложение. Но мы не можем остановиться на этом. Мы используем Serverless для автоматизации процесса развертывания. Ручная настройка поддержки бинарных файлов в консоли AWS — это определенно не то, что нам нужно. Давайте создадим плагин, который будет настраивать типы бинарных файлов для нас во время развертывания.

Мы будем хранить все в одном репозитории, в двух каталогах `example/express` (здесь будет находиться приложение) и `plugin`.

Перенесем наше приложение в подкаталог:

Создадим основной файл для нашего плагина и инициализируем npm-проект:

Нам нужно внести одно важное изменение в файл `package.json`. Убедитесь, что значение поля «main» — `src/index.js` (точный путь к точке входа нашего плагина). Ваш `package.json` плагина должен выглядеть примерно так:

Теперь мы можем начать писать плагин. Укажем основной класс для него и соответствующий конструктор (в файле `src/index.js`):

Попробуем использовать наш плагин с приложением:

Добавим плагин в вашу конфигурацию Serverless. Вставьте это в `serverless.yml`:

И посмотрим, будет ли сообщение «Hello world!» отображаться в консоли:

Мы должны увидеть вывод:

Ура! Идем дальше. Что мы будем делать сейчас, так это переместим наше сообщение в метод и привяжем его к хуку `after:deploy:deploy` (хуки описываются по соглашению `::`, поэтому наш хук означает: после того, как пользователи запустят команду `deploy`, выполнится `deploy` после метода `afterDeploy`). Вот как должен выглядеть файл `../../plugin/src/index.js` после этих изменений:

Выполнение `deploy` должно дать следующий вывод:

Ок. Плагин работает, хук работает. Теперь подключимся к AWS, используя их SDK, и внесем соответствующие изменения в только что развернутый API. Для начала укажем типы MIME в файле `serverless.yml` (соглашение: `custom -> pluginName -> values`):

Получим их в конструкторе плагина (`../../plugin/src/index.js`):

Дополнительные данные, которые нам нужно собрать, — это используемый провайдер и этап, на который мы развертываем:

Следующим шагом будет добавление метода `getApiId` в наш класс `BinarySupport`. Для этого мы будем использовать метод `describeStacks` из AWS SDK. Мы можем повторно использовать метод `request` из класса `serverless.provider`, потому что он содержит некоторую полезную логику, такую как поддержка различных профилей AWS и повторные попытки запросов в случае ошибки.

В качестве параметра нам нужно передать имя класса из AWS SDK (`CloudFormation`), метод, который мы хотим вызвать (`describeStacks`), и полезную нагрузку, которую мы хотим передать ему:

Попробуем. Обновим метод `afterDeploy` следующим кодом:

Для следующего шага нам нужен URL нашего только что развернутого API. Он скрыт в `Outputs: [Array]`. Выведем его. Внесем изменения в метод `afterDeploy` внутри `plugin/src/index.js`:

Если вы снова вызовете `npm run deploy` (из каталога `example/express`), вы должны получить в выводе эти строки:

Теперь у нас есть полная информация о только что развернутом стеке. Самое важное для нас находится в массиве `Outputs`. Там есть наш `ServiceEndpoint`, который содержит API ID. Отфильтруем этот вывод и получим этот ID:

Что мы собираемся сделать сейчас, так это поместить наши `binaryTypes` в этот API. Мы предоставим изменения в формате Swagger, поэтому подготовим их внутри нашего метода хука – `afterDeploy()`.

Добавьте следующий код в начало метода `afterDeploy()`:

Как видите, внутри JSON-тела константы `swaggerInput` мы предоставляем информацию о версии формата Swagger, заголовке нашего API (если мы этого не сделаем, AWS перезапишет имя нашего API значением по умолчанию) и `x-amazon-apigateway-binary-media-types`, куда мы передаем массив строк, представляющих типы MIME, предоставленные конфигурационным файлом `serverless.yml`.

Реализуем метод `getApiGatewayName` внутри нашего класса `BinarySupport`:

Ок. Мы собрали API ID и имя; теперь мы можем внести изменения. Для этого мы будем использовать метод `putRestApi` из AWS SDK и передавать информацию об изменениях, которые мы хотим выполнить:

Мы будем объединять все добавленные методы в хуке `after:deploy:deploy`. Обновим его:

Мы готовы протестировать наш плагин. Чтобы убедиться, что у нас нет старых развертываний, удалим их:

Теперь мы снова развернем приложение, войдем в консоль AWS и посмотрим на раздел `Binary Support`. Ура! Приложение там! Типы бинарных файлов есть! Перейдем к нему. О… проблема, опять. Красивая картинка пропала..

Причина проста. Вы помните, что мы переразвертывали API после любых изменений в нем? Это то, что мы забыли сделать с нашим плагином Serverless. Добавим этот шаг:

Теперь мы можем развернуть наше приложение и радоваться, потому что оно работает правильно, а процесс развертывания полностью автоматизирован!

Если вы хотите наверстать этот шаг:

Итак, у нас готов плагин. Он работает отлично. Что дальше? Теперь мы сделаем наш плагин доступным для всего мира!

У нас есть несколько способов сделать это.

Это очень просто. Вам нужно сделать две вещи.

Войдите в свою учетную запись npm через npm CLI:

И опубликуйте пакет:

Более интересно (по моему мнению) — развертывание через Git. Почему? Это дает вам возможность сделать ваш пакет доступным только для тех, кого вы хотите, чтобы он использовался (например, команда в вашей компании).

Единственное, что вам нужно сделать, — это отправить ваш код в репозиторий:

После этого, если вы хотите установить пакет в свой проект, вам нужно будет предоставить адрес вашего git-репозитория, например:

`npm install https://github.com/maciejtreder/serverless-apigw-binary.git`

В предыдущей статье мы узнали, как использовать фреймворк Serverless. Сегодня мы создали плагин Serverless с использованием AWS SDK для компенсации отсутствия стандартной поддержки бинарных файлов. Теперь мы готовы использовать эти знания и создать что-то потрясающее. В следующей статье мы создадим и развернем приложение Angular 4 на AWS Lambda!

Живую демонстрацию приложения, использованного в этой статье, можно найти здесь: https://serverless-apigw.maciejtreder.com

Git-репозиторий плагина: https://github.com/maciejtreder/serverless-apigw-binary

NPM-репозиторий плагина: https://www.npmjs.com/package/serverless-apigw-binary

Maciej Treder,

contact@maciejtreder.com

https://www.maciejtreder.com

@maciejtreder (GitHub, Twitter, StackOverflow, LinkedIn)