[アップデート] AWS LambdaのマネージドランタイムがNode.js 20をサポートしました

計画的なランタイムの更新を
2023.11.14

早く Node.js 20 使いたいな

こんにちは、のんピ(@non____97)です。

皆さんは早くLambdaで Node.js 20 使いたいなと思ったことはありますか? 私はあります。

LambdaのマネージドランタイムとしてNode.js 18がサポートされたのは2022/11/19で、そろそろ1年経ちます。

そろそろNode.js 20も来るか...? と思っていると来ました。

2023/11/14の10時時点ではAPI Referenceには反映されていないですが、AWS CLIのCommand Referenceには反映されていました。

--runtime (string)

The identifier of the function's runtime . Runtime is required if the deployment package is a .zip file archive.

The following list includes deprecated runtimes. For more information, see Runtime deprecation policy .

Possible values:

nodejs nodejs4.3 nodejs6.10 nodejs8.10 nodejs10.x nodejs12.x nodejs14.x nodejs16.x java8 java8.al2 java11 python2.7 python3.6 python3.7 python3.8 python3.9 dotnetcore1.0 dotnetcore2.0 dotnetcore2.1 dotnetcore3.1 dotnet6 nodejs4.3-edge go1.x ruby2.5 ruby2.7 provided provided.al2 nodejs18.x python3.10 java17 ruby3.2 python3.11 nodejs20.x provided.al2023

update-function-configuration — AWS CLI 1.29.85 Command Reference

早速確認してみます。

2023/11/16 追記 : What's NewとAWS Blogsにも来ました。

やってみる

AWS CDKでLambda関数をデプロイします。

まず、比較のためにNode.js18でデプロイします。

./lib/lambda-stack.ts

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as path from "path";

export class LambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new cdk.aws_lambda_nodejs.NodejsFunction(this, "Lambda", {
      entry: path.join(__dirname, "./lambda/handlers/node-js-20-handler.ts"),
      runtime: cdk.aws_lambda.Runtime.NODEJS_18_X,
      bundling: {
        minify: true,
        sourceMap: true,
        tsconfig: path.join(__dirname, "./lambda/tsconfig.json"),
        format: cdk.aws_lambda_nodejs.OutputFormat.ESM,
      },
      architecture: cdk.aws_lambda.Architecture.ARM_64,
      logRetention: cdk.aws_logs.RetentionDays.TWO_WEEKS,
      tracing: cdk.aws_lambda.Tracing.ACTIVE,
      timeout: cdk.Duration.seconds(10),
    });
  }
}

実行するコードは以下のとおりです。

./lib/lambda/handlers/node-js-20-handler.ts

export const handler = async (): Promise<void | Error> => {
  console.log(process.versions);

  return;
};

tsconfig.jsonは以下のとおりです。

./lib/lambda/tsconfig.json

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

Lambda関数の実行結果は以下のとおりです。Node.js 18で、V8は10.2であることが分かります。

INIT_START Runtime Version: nodejs:18.v18	Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:5b65a6230d1054ba2f3bcff29fe7654ff1a5453cd2cfa1a03367a850c540a9da
START RequestId: 51e82d4c-c770-44b9-bcaf-4e95823e67aa Version: $LATEST
2023-11-10T04:18:32.658Z	51e82d4c-c770-44b9-bcaf-4e95823e67aa	INFO	{
  node: '18.18.0',
  acorn: '8.10.0',
  ada: '2.6.0',
  ares: '1.19.1',
  brotli: '1.0.9',
  cldr: '43.1',
  icu: '73.2',
  llhttp: '6.0.11',
  modules: '108',
  napi: '9',
  nghttp2: '1.55.0',
  openssl: '3.1.3',
  simdutf: '3.2.14',
  tz: '2023c',
  undici: '5.22.1',
  unicode: '15.0',
  uv: '1.46.0',
  uvwasi: '0.0.18',
  v8: '10.2.154.26-node.26',
  zlib: '1.2.13.1-motley'
}
END RequestId: 51e82d4c-c770-44b9-bcaf-4e95823e67aa
REPORT RequestId: 51e82d4c-c770-44b9-bcaf-4e95823e67aa	Duration: 73.44 ms	Billed Duration: 74 ms	Memory Size: 128 MB	Max Memory Used: 67 MB	Init Duration: 173.84 ms	
XRAY TraceId: 1-654daf18-2a97cd0b2e55b3e1071e3f39	SegmentId: 36dad77f0795a40f	Sampled: true

続いて、Node.js 20でデプロイします。

AWS CDKではv2.107.0からLambdaでNode.js 20のランタイムを指定できるようになっています。

以下のようにランタイムとしてNode.js 20を指定してデプロイします。

./lib/lambda-stack.ts

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as path from "path";

export class LambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new cdk.aws_lambda_nodejs.NodejsFunction(this, "Lambda", {
      entry: path.join(__dirname, "./lambda/handlers/node-js-20-handler.ts"),
      runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
      bundling: {
        minify: true,
        sourceMap: true,
        tsconfig: path.join(__dirname, "./lambda/tsconfig.json"),
        format: cdk.aws_lambda_nodejs.OutputFormat.ESM,
      },
      architecture: cdk.aws_lambda.Architecture.ARM_64,
      logRetention: cdk.aws_logs.RetentionDays.TWO_WEEKS,
      tracing: cdk.aws_lambda.Tracing.ACTIVE,
      timeout: cdk.Duration.seconds(10),
    });
  }
}

デプロイ後のLambda関数の実行結果は以下のとおりです。Node.js 20で、V8は11.3になっていますね。

INIT_START Runtime Version: nodejs:20.v13	Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:6fb7e564fae3347add879359ec92013de1e84ce02488f36ec21448277c28707c
START RequestId: 5c8d8c46-8903-43c9-8a33-46a764466b82 Version: $LATEST
2023-11-14T00:55:11.076Z	5c8d8c46-8903-43c9-8a33-46a764466b82	INFO	{
  node: '20.9.0',
  acorn: '8.10.0',
  ada: '2.6.0',
  ares: '1.19.1',
  base64: '0.5.0',
  brotli: '1.0.9',
  cjs_module_lexer: '1.2.2',
  cldr: '43.1',
  icu: '73.2',
  llhttp: '8.1.1',
  modules: '115',
  napi: '9',
  nghttp2: '1.57.0',
  openssl: '3.1.3',
  simdutf: '3.2.17',
  tz: '2023c',
  undici: '5.26.3',
  unicode: '15.0',
  uv: '1.46.0',
  uvwasi: '0.0.18',
  v8: '11.3.244.8-node.16',
  zlib: '1.2.13.1-motley'
}
END RequestId: 5c8d8c46-8903-43c9-8a33-46a764466b82
REPORT RequestId: 5c8d8c46-8903-43c9-8a33-46a764466b82	Duration: 87.64 ms	Billed Duration: 88 ms	Memory Size: 128 MB	Max Memory Used: 65 MB	Init Duration: 146.20 ms	
XRAY TraceId: 1-6552c56e-02ec29f31601e434699eef45	SegmentId: 09a22080312b7ec0	Sampled: true

Node.js 20の新機能を試してみる

次にNode.js 20の新機能を試してみます。

Node.js 20の変更点の概要は以下Node.js公式ブログにまとまっています。

Node.js 19-20の詳細な変更点は以下Change logを確認するのが良いと思います。

個人的には、配列のソートや追加で元の配列を変更せずに処理できるようなメソッドが追加になったのが嬉しいです。このような破壊的なメソッドを使う場合際に行っていた、一度配列をコピーする手間が減ります。

実際に非破壊的なメソッドであるArray.prototype.toSorted()を試してみましょう。こちらのメソッドは要素を昇順にソートした新しい配列を返してくれます。

Array.prototype.toSorted()はES2023で追加されたメソッドです。tsconfig.jsonlibES2023を指定してあげます。

./lib/lambda/tsconfig.json

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2023"],
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

以下のようなコードでArray.prototype.toSorted()実行後に、元の配列が変更されているか確認します。

./lib/lambda/handlers/node-js-20-handler.ts

export const handler = async (): Promise<void | Error> => {
  const months = ["Mar", "Jan", "Feb", "Dec"];

  console.log(`Sorted months : ${months.toSorted()}`);
  console.log(`Original months : ${months}`);

  return;
};

実行結果は以下のとおりです。元の配列は変更されていませんね。

2023-11-14T01:17:36.292Z	b7f42417-3974-41fe-a8db-c0f727b7907f	INFO	Sorted months : Dec,Feb,Jan,Mar
2023-11-14T01:17:36.298Z	b7f42417-3974-41fe-a8db-c0f727b7907f	INFO	Original months : Mar,Jan,Feb,Dec

計画的なランタイムの更新を

AWS LambdaのマネージドランタイムがNode.js 20をサポートしたアップデートを紹介しました。

Node.js 18のEOLは2025/4/30です。計画的にNode.js 20への切り替えをしていきましょう。

抜粋 : nodejs/Release: Node.js Release Working Group

検証で使用したAWS CDKのコードは以下リポジトリに保存しています。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!