AWS Amplify CLIとTypeScriptでLambda関数の開発環境を構築する手順を学ぶ
まずはAWS Amplify CLIをインストール(バージョンは5.2.0だった)
npm i -g @aws-amplify/cli
適当にディレクトリ作って amplify init
する
mkdir ~/amplify-sample && cd $_
amplify init
プロジェクト名とか使うエディタとか使うAWS Profileとかとか色々聞かれるけど一旦適当に選択しておく。最悪 amplify delete
すればまた1からやり直せるし。。
処理が終わったら↓みたいな構成ができあがった
.
├── .gitignore
├── amplify
│ ├── #current-cloud-backend
│ │ ├── amplify-meta.json
│ │ └── tags.json
│ ├── .config
│ │ ├── local-aws-info.json
│ │ ├── local-env-info.json
│ │ └── project-config.json
│ ├── README.md
│ ├── backend
│ │ ├── amplify-meta.json
│ │ ├── backend-config.json
│ │ └── tags.json
│ ├── cli.json
│ └── team-provider-info.json
└── src
└── aws-exports.js
5 directories, 13 files
amplify add function
でプロジェクトにLambda関数を追加できるみたいなので実行する
実行したらまた色々聞かれたのでとりあえず今は↓みたいな感じにした
$ amplify add function
? Select which capability you want to add: Lambda function (serverless function)
? Provide an AWS Lambda function name: samplefunction
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World
Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration
? Do you want to configure advanced settings? No
? Do you want to edit the local lambda function now? No
Successfully added resource jobboardnotifier locally.
Functions - Build options - Amplify Docs にTypeScript導入例が書かれてたので参考にしてみる
TypeScriptはローカルインストールにしてみる
npm init
npm i -D typescript
npm init
で色々聞かれるやつはとりあえずEnterキー連打
amplify/backend/function/samplefunction/src
にトランスパイルしたjsを突っ込みたいので、tsファイルは amplify/backend/function/samplefunction/lib
に置くことにしてみる
cd amplify/backend/function/samplefunction
mkdir lib
# 一旦削除
rm src/event.json src/index.js
公式ドキュメントの例では tsconfig.json
を amplify/backend/function/samplefunction
の直下に置けとなってるのでそれに倣ってみる
npx tsc --init
公式ドキュメントに倣って tsconfig.json
を編集して一旦↓みたいな内容になった
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["DOM", "ESNext"],
"outDir": "./src",
"rootDir": "./lib",
"strict": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"src": ["./lib"]
},
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
}
}
構成ファイル '.../tsconfig.json' で入力が見つかりませんでした。指定された 'include' パスは '["**/*"]' で、'exclude' パスは '["./src"]' でした。
みたいなエラー出てるけど一旦無視
とりあえずまず動かしたいので Hello World 吐くだけのコードを書く
export const handler = () => {
console.log('Hello World');
}
公式ドキュメント見てると、プロジェクトルート(今回で言うと~/amplify-sampleディレクトリ)の package.json
に amplify:functionの名前
で実行できるnpm-scriptsを定義しておくと、amplify push
実行時に合わせて実行してくれるらしい。のでnpm-scriptsを追加する
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"amplify:jobboardnotifier": "cd amplify/backend/function/jobboardnotifier && tsc -p ./tsconfig.json && cd -"
},
amplify push
でトランスパイルできる的なことが書いてあるけど、とりあえずローカルで動かしたいので amplify mock
を試す
$ amplify mock function samplefunction
? Provide the path to the event JSON object relative to {プロジェクトルートのパス}/amplify/backend/function/samplefunction
>> Provide a valid unix-like path to a .json file
event.jsonどうしますか的なこと聞かれたので空にしてみたらjsonファイル指定しろと怒られた。。
のでevent.jsonを改めて追加する
echo "{}" > ~/amplify-sapmle/amplify/backend/function/samplefunction/src/event.json
再度 amplify mock
を試してみる
$ amplify mock function samplefunction
? Provide the path to the event JSON object relative to {プロジェクトルートのパス}/amplify/backend/function/job
boardnotifier src/event.json
Ensuring latest function changes are built...
Starting execution...
Hello World
samplefunction failed with the following error:
Error: Lambda execution timed out after 10 seconds. Press ctrl + C to exit the process.
To increase the lambda timeout use the --timeout parameter to set a value in seconds.
Note that the maximum Lambda execution time is 15 minutes:
https://aws.amazon.com/about-aws/whats-new/2018/10/aws-lambda-supports-functions-that-can-run-up-to-15-minutes/
at Timeout.<anonymous> (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-util-mock/src/func/index.ts:82:42)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
Finished execution.
おー動いた。が、エラーが出てる。
エラーが出てるのは関数がasync(Promise)でないといけないようで、そのPromiseが解決しないとタイムアウトになってしまうっぽい。のでasyncにして適当に解決させて再度 amplify mock
してみる
export const handler = async () => {
console.log('Hello World');
return {
statusCode: 200,
body: JSON.stringify({
message: 'Hello World'
})
};
}
$ amplify mock function samplefunction
? Provide the path to the event JSON object relative to {プロジェクトルートのパス}/amplify/backend/function/job
boardnotifier src/event.json
Ensuring latest function changes are built...
Starting execution...
Hello World
Result:
{
"statusCode": 200,
"body": "{\"message\":\"Hello World\"}"
}
Finished execution.
tsconfig.jsonのエラー解決やlintしたりできるようにしたいので、後日続きやる
amplify/backend/function/samplefunction/src
以下のjsも管理するのは煩わしいので .gitignore
に追記
@@ -17,4 +17,6 @@
amplify-build-config.json
amplify-gradle-config.json
amplifytools.xcconfig
.secret-*
-#amplify-do-not-edit-end
\ No newline at end of file
+#amplify-do-not-edit-end
+
+amplify/backend/function/jobboardnotifier/src/**/*.js
\ No newline at end of file
tsconig.json
でエラーがでる件については include
フィールドを追加すれば消えた。
…けどそれ以降includeフィールド消したりしてもエラーがでなくなったので謎。どうもVSCodeが出力するエラーっぽいのでまぁ一旦よしとする
@@ -16,5 +16,6 @@
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
- }
+ },
+ "include": ["./lib/**/*.ts"]
}
ここまでやってみて、どうせプロジェクトルートの tsc
使うなら tsconfig.json
もプロジェクトルートに置いてしまったほうが良いのかもしれないと思った。けどまぁあとで考える
lint周りの環境を整えようと思って、とりあえずeditorconfigを入れるために editorconfig-cli
というnpmモジュールが便利そうだったので使ってみた。インデントをスペースにしたくらいであとはEnter連打で良かったので楽。
$ npm i -g editorconfig-cli
$ ec init
? charset? utf-8
? indent style? space
? indent size? 2
? end of line? lf
? trim trailing whitespace? Yes
? insert final newline? Yes
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
? Ok? Yes
eslint
と prettier
は↓の記事を参考にやってみる
まずは eslint
環境整えるためにインストール
$ npm i -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
eslint
は --init
オプションで設定ファイル生成してくれるのでそれを実行する。TypeSciprt使いますか?みたいな質問もあってYesにしたら関連プラグインをインストールしてくれたので、もしかしたらとりあえずeslintだけインストールしてinitしたら概ね出来上がってしまうのかもしれない。便利ー。
$ npx eslint --init
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · standard
✔ What format do you want your config file to be in? · JSON
Checking peerDependencies of eslint-config-standard@latest
The config that you've selected requires the following dependencies:
@typescript-eslint/eslint-plugin@latest eslint-config-standard@latest eslint@^7.12.1 eslint-plugin-import@^2.22.1 eslint-plugin-node@^11.1.0 eslint-plugin-promise@^4.2.1 || ^5.0.0 @typescript-eslint/parser@latest
✔ Would you like to install them now with npm? · No / Yes
Installing @typescript-eslint/eslint-plugin@latest, eslint-config-standard@latest, eslint@^7.12.1, eslint-plugin-import@^2.22.1, eslint-plugin-node@^11.1.0, eslint-plugin-promise@^4.2.1 || ^5.0.0, @typescript-eslint/parser@latest
added 80 packages, and audited 229 packages in 5s
55 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Successfully created .eslintrc.json file
prettier
は eslint
の --init
では考慮されないみたいなので素直に入れる
$ npm i -D prettier eslint-config-prettier
@@ -4,7 +4,10 @@
"es2021": true
},
"extends": [
- "standard"
+ "standard",
+ "plugin:@typescript-eslint/recommended",
+ "prettier",
+ "prettier/@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
VSCodeでファイル保存時に勝手にフォーマットしてほしいので .vscode/settings.json
を↓の内容で追加
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
試しに lib/index.ts
を保存してみたらちゃんと自動フォーマットされたので、とりあえず求めてた環境構築はできた!
apmlifyでfunction開発する場合のDefinedTypeがないか探してみたけど、具体的に言及されてるような記事等は見つからなかった。ので一旦 @types/aws-lambda
を導入して開発してみようと思う