echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【AWS CDK】LambdaをTypeScriptで動かす環境を構築する(その2:AWS CDKでの実装&TypeScriptで動作させる)

はじめに

本ブログは、2025/02/21(金)に開催された「JAWS-UG CDK支部#19 クラスメソッドコラボ回」における私のLT「CDKでカスタムランタイムを作成して、Lambdaをnode.js23+TypeScriptで動かしてみた」の詳細資料になります。

https://jawsug-cdk.connpass.com/event/343974/jawsug-cdk.connpass.com

LTの発表資料は、下記で公開しています。(上記Connpassページにもリンクがあります)

speakerdeck.com

なお今回は下記の構成で、何回かに分けて投稿します。

  1. カスタムランタイム作成 ※前回の記事
  2. AWS CDKでの実装&TypeScriptで動作させる ※今回はこれ
  3. AWSリソースにアクセスする(AWS SDK for JavaScript v3を使う)

AWS CDKでLambdaレイヤーを作成する

前回、Node.js ver23.6.0のカスタムランタイムをLambdaレイヤーで作成しましたが、まずはこのLambdaレイヤーをAWS CDK(以下「CDK」)作成する必要があります。

ただAWS CDKは LayerVersion コンストラクタでLambdaレイヤー作成できるので、下記の定義を行うだけでOKです。*1

// コンストラクタ変数は後で使います
// 「runtime-tutorial」フォルダは、前回使用したフォルダ(詳細は前回を参照)
// compatibleArchitecturesやcompatibleRuntimesも指定する
const node23RuntimeLayer = new lambda.LayerVersion(this, 'Node23SampleLayer', {
    code: lambda.Code.fromAsset(<runtime-tutorialフォルダのパス>),
    layerVersionName: 'runtime-node23-jawsug-cdk-event-19',
    removalPolicy: cdk.RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
});

Lambda関数を作成する

次にLambda関数(TypeScript)です。

なお今回Lambda関数をTypeScriptで作成しますが、使うコンストラクタは「Function」になりますので注意で す。
(「NodejsFunction」だとデプロイ時にJavaScriptへのトランスパイルが行われてしまうので)

あとはruntimeruntime: lambda.Runtime.PROVIDED_AL2023 (Amazon Linux 2023)を選択すればOKです。(その他の項目は以下参照)

もちろん layers に先ほど作成したLambdaレイヤーを指定するのを忘れないでください。

const node23SampleFunction = new lambda.Function(this, "Node23SampleFunction", {
    functionName: 'Node23SampleFunction',
    runtime: lambda.Runtime.PROVIDED_AL2023, // Amazon Linux 2023を指定
    layers: [node23RuntimeLayer],  // ここで上記のLambdaレイヤーを指定
    handler: "index.handler",
    code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')),  // Lambdaソースファイルのパス
});

なおLambdaソースは、前回の「使用しているNode.jsのバージョンを返す」をTypeScriptで書いただけのものです。(1行目の import については後で触れます)

import type { LambdaFunctionURLEvent, LambdaFunctionURLResult } from 'aws-lambda/trigger/lambda-function-url'
  
const handler = async function (event: LambdaFunctionURLEvent) {
  console.log(event);
  
  const result: LambdaFunctionURLResult = {
    statusCode: 200,
    body: JSON.stringify({
      message: `node version is ${process.version}`
    }),
  };
  
  return result;
};

module.exports = { handler }

runtime.js を変更する

そしてもう一つ、前回作成したruntime.js も更新が必要です。
現時点でruntime.jsの内容はJavaScript(*.js)にのみ対応しているので(Node.jsなので)、TypeScriptに対応するように変更する必要があります。

これはruntime.jsの148行目あたりにある下記ソースを、以下の通りに変更すればOKです。*2

# 末尾に「.ts」を追加し、TypeScriptファイルを読めるようにする
- const app = require(LAMBDA_TASK_ROOT + '/' + modulePath);
+ const app = require(LAMBDA_TASK_ROOT + '/' + modulePath + ".ts");

「型除去(Type Stripping)」について

1行目のimport文ですが、import type という見慣れない記載になっています。

これはnode.jsでTypeScriptを動かす際の独自の仕様である「型除去(Type Stripping)」に関わるものです。

「型除去(Type Stripping)」とは、TypeScriptファイルを 「型だけ削除して実行」するためのもの で、以前はオプションでしたが、v23.6.0からデフォルトで有効になっています。*3

ただし「型」ということを明示的に示すために、型定義のインポート/エクスポート時はtype という言葉を明示的に記載する必要があります。(これを忘れると「型」と認識されないため型除去は行われず、エラーになることがあります)

またこの型除去がデフォルトになったことで、tsconfig.json の下記項目もチェックする必要があります。(今回のLambdaの挙動には影響しません)

設定値 説明 デフォルト値
allowImportingTsExtensions *.tsファイルからのインポートを可能にする rewriteRelativeImportExtensionsが有効な場合はtrue,そうでない場合はfalse
rewriteRelativeImportExtensions 相対インポートパス内の .ts、.tsx、.mts、および .cts ファイル拡張子を、出力ファイル内の対応する JavaScript に書き換える 未記載
verbatimModuleSyntax 型のimport/export時に「type」が未記載の場合、エラーとする 未記載

実行する

ここまで来たら、あとはcdk deploy でデプロイして、前回同様AWSコンソールからLambda関数の「テスト」で実施するだけです。
問題なければ、前回同様「node version is v23.6.0」という結果が返ってくるはずです。

まとめ

というわけで、ここまでで「AWS CDKでの実装&TypeScriptで動作させる」部分まで完了しました。

次回は最終回として「AWS SDK for JavaScript v3を使ってAWSリソースにアクセスする」ことを実施しようと思います。

告知

5/23(金)~5/24(土)に東京・ベルサール神田で実施される「TS Kaigi 2025」にて、「AWS LambdaをTypeScriptで動かして分かった、Node.jsのTypeScriptサポートの利点と課題」登壇させていただくこととなりました。(日時は5/23(金) 15:50 ~ 16:20 の予定です)

2025.tskaigi.org

ちょうどこのブログで扱っている「【AWS CDK】LambdaをTypeScriptで動かす環境を構築する」で分かったNode.jsのTypeScriptサポートを触ってみてわかったことをお話しさせていただきますので、当日はよろしくお願いいたします。

それでは、今回はこの辺で。

*1:発表資料にも書きましたが、AWS CDKでカスタムランタイムを作成すること自体は、全く難しくないです。作成することと自体は、ですが...

*2:ただし下記の変更だと、今度はJavaScriptファイルが読めないので、柔軟に対応するにはもっと細かい変更が必要です。

*3:ただしにコマンドラインで実行する場合、--disable-warning=ExperimentalWarning フラグを使用して警告を非表示にしないと「ExperimentalWarning: Type Stripping is an experimental feature and might change at any time」という警告が出ますので注意が必要です