タイトルの構成でやろうと思ったら意外と面倒だったので、次回セットアップを楽にするためのめも
↓の資料はだいたい同じ内容で参考にさせてもらいました
前提
- SAM CLI is installed
- Docker is installed
TL;DR
ここに上げた
sam init
注意点として、init するときに package type = Image にすると、TypeScript のテンプレートを CLI に作ってもらえなくなる。なので、ここではいったん package type = Zip にする
抜粋
What package type would you like to use? 1 - Zip 2 - Image Package type: 1 Based on your selections, the only dependency manager available is npm. We will proceed copying the template using npm. Select your starter template 1 - Hello World Example 2 - Hello World Example TypeScript Template: 2
全部
❯ sam init You can preselect a particular runtime or package type when using the `sam init` experience. Call `sam init --help` to learn more. Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Choose an AWS Quick Start application template 1 - Hello World Example 2 - Data processing 3 - Hello World Example with Powertools for AWS Lambda 4 - Multi-step workflow 5 - Scheduled task 6 - Standalone function 7 - Serverless API 8 - Infrastructure event management 9 - Lambda Response Streaming 10 - Serverless Connector Hello World Example 11 - Multi-step workflow with Connectors 12 - GraphQLApi Hello World Example 13 - Full Stack 14 - Lambda EFS example 15 - Hello World Example With Powertools for AWS Lambda 16 - DynamoDB Example 17 - Machine Learning Template: 1 Use the most popular runtime and package type? (Python and zip) [y/N]: n Which runtime would you like to use? 1 - aot.dotnet7 (provided.al2) 2 - dotnet6 3 - go1.x 4 - go (provided.al2) 5 - go (provided.al2023) 6 - graalvm.java11 (provided.al2) 7 - graalvm.java17 (provided.al2) 8 - java21 9 - java17 10 - java11 11 - java8.al2 12 - java8 13 - nodejs20.x 14 - nodejs18.x 15 - nodejs16.x 16 - python3.9 17 - python3.8 18 - python3.12 19 - python3.11 20 - python3.10 21 - ruby3.2 22 - ruby2.7 23 - rust (provided.al2) 24 - rust (provided.al2023) Runtime: 13 What package type would you like to use? 1 - Zip 2 - Image Package type: 1 Based on your selections, the only dependency manager available is npm. We will proceed copying the template using npm. Select your starter template 1 - Hello World Example 2 - Hello World Example TypeScript Template: 2 Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: n Would you like to enable monitoring using CloudWatch Application Insights? For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: n Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N]: n Project name [sam-app]: sam-typescript-demo ----------------------- Generating application: ----------------------- Name: sam-typescript-demo Runtime: nodejs20.x Architectures: x86_64 Dependency Manager: npm Application Template: hello-world-typescript Output Directory: . Configuration file: sam-typescript-demo/samconfig.toml Next steps can be found in the README file at sam-typescript-demo/README.md Commands you can use next ========================= [*] Create pipeline: cd sam-typescript-demo && sam pipeline init --bootstrap [*] Validate SAM template: cd sam-typescript-demo && sam validate [*] Test Function in the Cloud: cd sam-typescript-demo && sam sync --stack-name {stack-name} --watch
コード修正
やることは
ここ↓に Dockerfile とかもろもろ中身が書いてあるので、基本的にこれに沿って進める
ファイルのリネーム
init でできた hello-world/app.ts
を hello-world/index.ts
に変える。なぜかというと、このあとコピペするファイルが index.ts
前提なのでその方が楽になるから。 app.ts
のままでももちろんできるけど、以降の作業がちょっと変わる。
Dockerfile
hello-world/Dockerfile
を作成して、上のリンクの中身をペーストする。ただし、
- image の node version
- CMD
が違う可能性があるので、適宜修正する。
2024年1月現在だと、ドキュメントは
FROM public.ecr.aws/lambda/nodejs:18 as builder
となっているけど、自分は nodejs:20
を追加したいので変えた。
CMD については、公式は CMD ["index.handler"]
と書いているけど、init でできたコードは lambdaHandler
と微妙に違うのでそれも直す。
最終できたのはこれ
# hello-world/Dockerfile FROM public.ecr.aws/lambda/nodejs:20 as builder # changed from nodejs:18 WORKDIR /usr/app COPY package.json index.ts ./ RUN npm install RUN npm run build FROM public.ecr.aws/lambda/nodejs:20 # changed from nodejs:18 WORKDIR ${LAMBDA_TASK_ROOT} COPY --from=builder /usr/app/dist/* ./ CMD ["index.lambdaHandler"] # changed from index.handler
package.json の修正
TS → JS に transpile するので、そのための build
コマンドも追加する
これは最初の Deploy transpiled ... のリンクに書いてあるとおりのコマンドを貼り付ければ OK
... "scripts": { "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js", ... } ...
template.yaml の修正
これは Resources > HelloWorldFunction
の中を zip 用から image 用に変える。変える先のコードは、別のディレクトリで sam init
を JS x package type = Zip で実行して、その template.yaml を見ながらコピペした。
最終こうなればおーけー。
# ... Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: PackageType: Image Architectures: - x86_64 Architectures: - x86_64 Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get Metadata: DockerTag: nodejs20.x-v1 DockerContext: ./hello-world Dockerfile: Dockerfile # ...
動作確認
$ sam build $ sam local invoke
これが両方通れば大丈夫なはず!
その他
vitest を入れる
インストールして、
- テストファイルのインポートを jest から vitest に書き換える (vitest は jest 互換あるのでたぶん
import { ... } from "vitest"
に書き換えるだけでいけるはず)
$ npm install -D test
以下は任意だけど、やっておくとテストファイルごとに vitest
から expect
などをインポートしなくてもよくなる
hello-world/vitest.config.ts を追加
/// <reference types="vitest" /> import { defineConfig } from "vite"; // https://vitejs.dev/config/ export default defineConfig({ test: { globals: true, }, });
hello-world/tsconfig.json に追記
"types": ["vitest/globals"],
alias の設定
hello-world/packaage.json
に以下を追記
"test": "vitest"
alias の設定
import ... from "@/..." をやるための設定
tsconfig.json
の "compilerOptions" に以下を追記
"baseUrl": ".", "paths": { "@/*": ["*"] }
あわせて vitest.config.ts もかぞえる
... resolve: { alias: { '@': path.resolve(__dirname, '.'), }, }, ...
その他
今 cd hello-world && npm run test
を実行したら、 "command not found: tsc" が出ちゃうことに気がついたので、これは別で対応予定