AWS Lambda で Node.js アプリケーションを実行する際、依存関係を含めたパッケージングはデプロイの成否を左右する重要な工程です。pkg(Vercel 製)は Node.js プロジェクトを単一の実行可能ファイルに変換し、ランタイム環境の差異を吸収しながら、コールドスタートやパッケージサイズの課題を解決します。本記事では、pkg を用いて Lambda 関数向けに最適化されたパッケージを作成する手順を詳しく解説します。
pkg が AWS Lambda にもたらす利点
- コールドスタートの短縮: 動的ロードが不要なため、起動時間が平均 30% 以上改善されます。
- デプロイパッケージの小型化: 不要なファイルを自動除外し、サイズを 40~60% 削減できます。
- 環境の再現性: バイナリに Node.js ランタイムが組み込まれるため、Lambda 環境との整合性が保たれます。
pkg を用いた Lambda 向けパッケージングの実践
1. ツールのインストール
npm install -g pkg
# またはプロジェクトローカルに
npm install pkg --save-dev
2. package.json の設定
エントリポイントとターゲットプラットフォームを指定します。
{
"name": "lambda-function",
"main": "handler.js",
"pkg": {
"scripts": "handler.js",
"assets": ["config/*.json"],
"targets": ["node18-linux-x64"]
}
}
3. 実行可能ファイルの生成
pkg . --targets node18-linux-x64 --output bootstrap
生成された bootstrap ファイルが Lambda のカスタムランタイムエントリポイントとして動作します。
4. デプロイパッケージの作成
mkdir deploy
cp bootstrap deploy/
zip -j deploy/function.zip deploy/bootstrap
パフォーマンス最適化のための追加設定
依存関係の除外
{
"pkg": {
"exclude": ["aws-sdk", "sharp"]
}
}
aws-sdk は Lambda 環境にプリインストールされているため、除外してサイズを削減できます。
アセットのバンドル
{
"pkg": {
"assets": ["views/**/*.ejs", "public/**/*"]
}
}
テンプレートや静的ファイルを明示的に含めます。
動的 require への対応
{
"pkg": {
"scripts": "src/**/*.js"
}
}
動的にロードされるモジュールは事前に指定しておく必要があります。
トラブルシューティング
- ネイティブモジュエルのエラー:
--no-bytecodeオプションを試すか、ビルド環境を Lambda の Amazon Linux 2 に合わせてください。 - パス問題:
__dirnameの参照先が変わるため、絶対パスを使用してください。
デプロイと検証
aws lambda update-function-code --function-name my-function --zip-file fileb://deploy/function.zip
aws lambda invoke --function-name my-function --payload '{}' output.txt
まとめ
pkg によるパッケージングは、Node.js アプリケーションを Lambda にデプロイする際の標準的な手法として定着しつつあります。適切な設定と最適化を施すことで、軽量で高速なサーバーレスアプリケーションを構築できます。Lambda 関数のパフォーマンス向上を目指す場合は、ぜひ導入を検討してみてください。