TypeScriptとJestサポートの操作:AWSSAMチュートリアル
公開: 2022-03-11サーバーレスアプリケーションを構築するための強力なツールであるAWSサーバーレスアプリケーションモデル(SAM)は、JavaScriptと頻繁にペアになります。中規模および大規模企業の開発者の62%が、サーバーレスコードにJavaScriptを選択しています。 ただし、TypeScriptの人気は急上昇しており、開発者の3番目に愛されている言語としてJavaScriptをはるかに上回っています。
JavaScriptの定型文を見つけるのは難しいことではありませんが、TypeScriptを使用してAWSSAMプロジェクトを開始することはより複雑です。 次のチュートリアルでは、AWS SAM TypeScriptプロジェクトを最初から作成する方法と、さまざまな部分がどのように連携するかを示します。 読者は、AWSLambda関数にある程度精通している必要があります。
AWSSAMTypeScriptプロジェクトの開始
サーバーレスアプリケーションの基盤には、さまざまなコンポーネントが含まれています。 まず、AWS環境、npmパッケージ、およびWebpack機能を構成します。次に、Lambda関数を作成、呼び出し、テストして、アプリケーションの動作を確認します。
環境を整える
AWS環境をセットアップするには、以下をインストールする必要があります。
- AWSCLI
- AWS SAM CLI
- Node.jsとnpm
このチュートリアルでは、アプリケーションをローカルでテストするために、上記の手順2でDockerをインストールする必要があることに注意してください。
空のプロジェクトを初期化する
プロジェクトディレクトリ、 aws-sam-typescript-boilerplate 、およびコードを保持するsrcサブフォルダーを作成しましょう。 プロジェクトディレクトリから、新しいnpmパッケージを設定します。
npm init -y # -y option skips over project questionnaire このコマンドは、プロジェクト内にpackage.jsonファイルを作成します。
Webpack構成を追加する
Webpackは、主にJavaScriptアプリケーションに使用されるモジュールバンドラーです。 TypeScriptはプレーンなJavaScriptにコンパイルされるため、WebpackはWebブラウザー用にコードを効果的に準備します。 2つのライブラリとカスタムローダーをインストールします。
- webpack:コアライブラリ
- webpack-cli:Webpackのコマンドラインユーティリティ
- ts-loader:Webpack用のTypeScriptローダー
npm i --save-dev webpack webpack-cli ts-loader AWS SAMCLI sam buildコマンドであるsambuildは、関数ごとにnpm installを実行しようとするため、開発プロセスが遅くなり、重複が発生します。 aws-sam-webpack-pluginライブラリの代替ビルドコマンドを使用して、環境を高速化します。
npm i --save-dev aws-sam-webpack-plugin デフォルトでは、Webpackは構成ファイルを提供しません。 ルートフォルダにwebpack.config.jsという名前のカスタム設定ファイルを作成しましょう。
/* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path'); const AwsSamPlugin = require('aws-sam-webpack-plugin'); const awsSamPlugin = new AwsSamPlugin(); module.exports = { entry: () => awsSamPlugin.entry(), output: { filename: (chunkData) => awsSamPlugin.filename(chunkData), libraryTarget: 'commonjs2', path: path.resolve('.') }, devtool: 'source-map', resolve: { extensions: ['.ts', '.js'] }, target: 'node', mode: process.env.NODE_ENV || 'development', module: { rules: [{ test: /\.tsx?$/, loader: 'ts-loader' }] }, plugins: [awsSamPlugin] };それでは、さまざまな部分を調べてみましょう。
-
entry:これは、AWS::Serverless::Functionリソースからエントリーオブジェクト(Webpackがバンドルの構築を開始する場所)をロードします。 -
output:これは、ビルド出力の宛先(この場合は.aws-sam/build)を指します。 ここでは、ターゲットライブラリをcommonjs2として指定します。これにより、エントリポイントの戻り値がmodule.exportsに割り当てられます。 このエントリポイントは、Node.js環境のデフォルトです。 -
devtool:これにより、ビルド出力先にソースマップapp.js.mapが作成されます。 元のコードをWebブラウザーで実行されているコードにマップし、環境変数NODE_OPTIONSをLambda--enable-source-mapsに設定するとデバッグに役立ちます。 -
resolve:これは、JavaScriptファイルの前にTypeScriptファイルを処理するようにWebpackに指示します。 -
target:これはWebpackにNode.jsを環境としてターゲットにするように指示します。 これは、Webpackがコンパイル時にチャンクをロードするためにrequire関数を使用することを意味します。 -
module:これは、test条件を満たすすべてのファイルにTypeScriptローダーを適用します。 つまり、拡張子が.tsまたは.tsxのすべてのファイルがローダーによって処理されるようになります。 -
plugins:これは、Webpackがaws-sam-webpack-plugin識別して使用するのに役立ちます。
最初の行では、このファイルの特定のESLintルールを無効にしています。 後で構成する標準のESLintルールは、 requireステートメントを使用しないようにします。 例外を作成するために、Webpackにimport requireがあります。
TypeScriptサポートを設定する
TypeScriptサポートを追加すると、次の方法で開発者のエクスペリエンスが向上します。
- 型宣言の欠落に関する警告メッセージの防止。
- タイプ検証を提供します。
- IDE内でオートコンプリートを提供します。
まず、プロジェクトのTypeScriptをローカルにインストールします(TypeScriptをグローバルにインストールしている場合は、この手順をスキップしてください)。
npm i --save-dev typescript使用しているライブラリのタイプを含めます。
npm i --save-dev @types/node @types/webpack @types/aws-lambda 次に、プロジェクトルートにTypeScript構成ファイルtsconfig.jsonを作成します。
{ "compilerOptions": { "target": "ES2015", "module": "commonjs", "sourceMap": true, "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, }, "include": ["src/**/*.ts", "src/**/*.js"], "exclude": ["node_modules"] } ここでは、TypeScriptコミュニティが推奨するデフォルトの構成に従います。 srcフォルダーの下のファイルをプログラムに追加するためのincludeを追加し、 node_modulesフォルダーのTypeScriptコンパイルを回避するためにexcludeを追加しました。このコードには直接触れません。
ラムダ関数を作成する
これまでサーバーレスアプリケーション用のLambdaコードを記述していないので、ジャンプしてみましょう。前に作成したsrcフォルダーに、このLambda関数を使用してapp.tsファイルを含むtest-lambdaサブフォルダーを作成します。
import { APIGatewayEvent } from 'aws-lambda'; export const handler = async (event: APIGatewayEvent) => { console.log('incoming event is', JSON.stringify(event)); const response = { statusCode: 200, body: JSON.stringify({ message: 'Request was successful.' }) }; return response; };この単純なプレースホルダー関数は、本文を含む200応答を返します。 もう1つの手順を実行すると、コードを実行できるようになります。
AWSテンプレートファイルを含める
AWS SAMには、コードをトランスパイルしてクラウドにデプロイするためのテンプレートファイルが必要です。 ルートフォルダにファイルtemplate.yamlを作成します。
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: AWS SAM Boilerplate Using TypeScript Globals: Function: Runtime: nodejs14.x # modify the version according to your need Timeout: 30 Resources: TestLambda: Type: AWS::Serverless::Function Properties: Handler: app.handler FunctionName: "Test-Lambda" CodeUri: src/test-lambda/ Events: ApiEvent: Type: Api Properties: Path: /test Method: get このテンプレートファイルは、HTTPGETAPIからアクセス可能なLambda関数を生成します。 Runtime:行で参照されているバージョンはカスタマイズが必要な場合があることに注意してください。
アプリケーションを実行する
アプリケーションを実行するには、Webpackを使用してプロジェクトをビルドするための新しいスクリプトをpackage.jsonファイルに追加する必要があります。 ファイルには、空のテストスクリプトなどの既存のスクリプトが含まれている場合があります。 次のようなビルドスクリプトを追加できます。
"scripts": { "build": "webpack-cli" } プロジェクトのルートからnpmrunbuildをnpm run buildと、ビルドフォルダー.aws-samが作成されていることがわかります。 Mac環境にいる私たちの場合、 Command +Shift+を押して隠しファイルを表示する必要があるかもしれません。 フォルダを表示します。
次に、ローカルHTTPサーバーを起動して、機能をテストします。
sam local start-apiWebブラウザーでテストエンドポイントにアクセスすると、成功メッセージが表示されます。
コンソールは、関数が実行される前にDockerコンテナーにマウントされていることを示す必要があります。そのため、以前にDockerをインストールしました。
Invoking app.handler (nodejs14.x) Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs14.x:rapid-1.37.0-x86_64. Mounting /Users/mohammadfaisal/Documents/learning/aws-sam-typescript-boilerplate/.aws-sam/build/TestLambda as /var/task:ro, delegated inside runtime containerプロフェッショナルな設定のための開発ワークフローの強化
私たちのプロジェクトは稼働中であり、いくつかの仕上げを追加することで、生産性とコラボレーションを向上させる優れた開発者エクスペリエンスが保証されます。

ホットリロードでビルドを最適化する
コードを変更するたびにビルドコマンドを実行するのは面倒です。 ホットリロードはこの問題を修正します。 package.jsonに別のスクリプトを追加して、ファイルの変更を監視できます。
"watch": "webpack-cli -w" 別のターミナルを開き、 npm run watchます。 これで、コードを変更するとプロジェクトが自動的にコンパイルされます。 コードのメッセージを変更し、Webページを更新して、更新された結果を確認します。
ESLintとPrettierでコード品質を向上させる
TypeScriptまたはJavaScriptプロジェクトは、ESLintとPrettierなしでは完成しません。 これらのツールは、プロジェクトのコード品質と一貫性を維持します。
最初にコア依存関係をインストールしましょう:
npm i --save-dev eslint prettierESLintとPrettierがTypeScriptプロジェクトで連携できるように、いくつかのヘルパー依存関係を追加します。
npm i --save-dev \ eslint-config-prettier \ eslint-plugin-prettier \ @typescript-eslint/parser \ @typescript-eslint/eslint-plugin 次に、プロジェクトルート内にESLint構成ファイル.eslintrcを作成して、リンターを追加します。
{ "root": true, "env": { "es2020": true, "node": true, "jest": true }, "parser": "@typescript-eslint/parser", "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], "ignorePatterns": ["src/**/*.test.ts", "dist/", "coverage/", "test/"], "parserOptions": { "ecmaVersion": 2018, "sourceType": "module", "ecmaFeatures": { "impliedStrict": true } }, "rules": { "quotes": ["error", "single", { "allowTemplateLiterals": true }], "default-case": "warn", "no-param-reassign": "warn", "no-await-in-loop": "warn", "@typescript-eslint/no-unused-vars": [ "error", { "vars": "all", "args": "none" } ] }, "settings": { "import/resolver": { "node": { "extensions": [".js", ".jsx", ".ts", ".tsx"] } } } } PrettierエラーをESLintエラーとしてエディターに表示するには、ファイルのextendsセクションでPrettierプラグイン構成を最後の行として保持する必要があることに注意してください。 TypeScriptのESLint推奨設定に従い、 rulesセクションにいくつかのカスタム設定を追加します。 利用可能なルールを参照して、設定をさらにカスタマイズしてください。 以下を含めることにしました。
- 一重引用符で囲まれた文字列を使用しない場合のエラー。
-
switchステートメントにdefaultのケースを指定しない場合の警告。 - 関数のパラメータを再割り当てした場合の警告。
- ループ内で
awaitステートメントを呼び出した場合の警告。 - 未使用の変数のエラー。コードが読み取れなくなり、時間の経過とともにバグが発生しやすくなります。
Prettierフォーマットで動作するようにESLint構成をすでにセットアップしました。 (詳細については、 eslint-config-prettier GitHubプロジェクトを参照してください。)これで、Prettier構成ファイル.prettierrcを作成できます。
{ "trailingComma": "none", "tabWidth": 4, "semi": true, "singleQuote": true }これらの設定は、Prettierの公式ドキュメントからのものです。 必要に応じて変更できます。 次のプロパティを更新しました。
-
trailingComma:末尾のコンマを避けるために、これをes5からnoneに変更しました。 -
semi:各行の最後にセミコロンを付けることを好むため、これをfalseからtrueに変更しました。
最後に、ESLintとPrettierの動作を確認します。 app.tsファイルで、 response変数の型をconstからletに変更します。 この場合、 responseの値を変更しないため、 letを使用することはお勧めできません。 エディターは、エラー、違反したルール、およびコードを修正するための提案を表示する必要があります。 ESLintとPrettierがまだ設定されていない場合は、それらをエディターで有効にすることを忘れないでください。
Jestテストでコードを維持する
Jest、Mocha、Storybookなど、多くのライブラリをテストできます。 いくつかの理由で、プロジェクトでJestを使用します。
- 学ぶのは速いです。
- 最小限のセットアップで済みます。
- 使いやすいスナップショットテストを提供します。
必要な依存関係をインストールしましょう:
npm i --save-dev jest ts-jest @types/jest 次に、プロジェクトルート内にJest構成ファイルjest.config.jsを作成します。
module.exports = { roots: ['src'], testMatch: ['**/__tests__/**/*.+(ts|tsx|js)'], transform: { '^.+\\.(ts|tsx)$': 'ts-jest' } };ファイル内の3つのオプションをカスタマイズしています。
-
roots:この配列には、テストファイルを検索するフォルダーが含まれていますsrcサブフォルダーの下でのみチェックされます。 -
testMatch:このグロブパターンの配列には、Jestファイルと見なされるファイル拡張子が含まれています。 -
transform:このオプションを使用すると、ts-jestパッケージを使用してTypeScriptでテストを記述できます。
src/test-lambda内に新しい__tests__フォルダーを作成しましょう。 その中に、ファイルhandler.test.tsを追加します。ここで、最初のテストを作成します。
import { handler } from '../app'; const event: any = { body: JSON.stringify({}), headers: {} }; describe('Demo test', () => { test('This is the proof of concept that the test works.', async () => { const res = await handler(event); expect(res.statusCode).toBe(200); }); }); package.jsonファイルに戻り、テストスクリプトで更新します。
"test": "jest" ターミナルに移動してnpm run testと、合格したテストが表示されます。
.gitignoreソース管理を処理する
特定のファイルをソース管理から除外するようにGitを構成する必要があります。 gitignore.ioを使用して.gitignoreファイルを作成し、不要なファイルをスキップできます。
# Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* .pnpm-debug.log* # Runtime data pids *.pid *.seed *.pid.lock npm-debug.log package.lock.json /node_modules .aws-sam .vscode # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional ESLint cache .eslintcache準備、設定、構築:成功のための青写真
これで、TypeScriptを使用した完全なAWSSAMボイラープレートプロジェクトができました。 私たちは、ESLint、Prettier、およびJestのサポートにより、基本を正しく理解し、高いコード品質を維持することに重点を置いてきました。 このAWSSAMチュートリアルの例は、最初から次の大きなプロジェクトを軌道に乗せるための青写真として役立ちます。
Toptal Engineering Blogは、この記事で紹介されているコードサンプルをレビューしてくれたChristianLoefに感謝の意を表します。
