Share
Embed
Amplify Gen2 Deep Dive / バックエンドの型をいかにしてフロントエンドへ伝えるか #TSKaigi #TSKaigiKansai #AWSAmplifyJP
TSKaigi Kansai 2024 登壇資料。
https://kansai.tskaigi.org/talks/tacck
Kihara, Takuya PRO
November 16, 2024
Video
Transcript
79 slides
-
Amplify Gen2 Deep Dive バックエンドの型をいかにして フロントエンドへ伝えるか TSKaigi Kansai 2024 2024/11/16
Kihara, Takuya (@tacck) TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 1 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 2 Kihara, Takuya 木原 卓也 / @tacck / Sapporo, Japan CO-OP Sapporo 生活協同組合コープさっぽろ Software Engineer / Flutter, TypeScript, Vue.js, React Amplify Japan User Group 運営メンバー ゆるWeb勉強会@札幌 主催 AWS Community Builder Since Q2 2021 / Category: Front-end Web and Mobile Community 好きなフィギュアスケートの技 スプレッド・イーグル -
Amplify Japan User Group AWS Amplify に関する情報発信・ミートアップを開催。 TSKaigi Kansai 2024
/ #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 3 -
今日のお話 ▪ Amplify Gen2 – AWS Amplify とは – Amplify
Gen2 の開発者体験(DX)強化 – Sandbox – バックエンドとフロントエンド・リソースの連携 ▪ Deep Dive in Code – フィールド・モデル・スキーマの型 – フロントエンドへの型連携 – Sandbox での CDK 実行 TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 4 -
AMPLIFY GEN2 TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify
Gen2 Deep Dive 5 -
AWS Amplify とは ▪ フロントエンドアプリケーションを開発するための、サービスおよびツール群。 – CI/CD を備えたホスティングサービス – Git
branches をベースとしたデプロイ先の切り分け – AWS リソース(Cognito, S3, AppSync, etc) のためのライブラリ群 – Web フロントエンド用ライブラリ ▪ React / Next.js / Angular / Vue / JavaScript – スマートフォンアプリ用ライブラリ ▪ React Native / Flutter / Android / Swift ▪ mBaaS → フロントエンドホスティング強化 → フロントエンド開発者体験強化 TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 6 -
開発者体験 (Developer Experience) 強化 ▪ TypeScript での開発強化 – Web フロントエンドライブラリの
TypeScript 対応 – バックエンドリソースの TypeScript での宣言 – Lambda Functions の TypeScript 実装対応 – etc... ▪ 開発中の Sandbox 機能追加 (開発環境をAWSへ即時反映) – Run CDK with hotswapping TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 7 -
Sandbox とは TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify
Gen2 Deep Dive 8 ▪ 開発者のマシンとAWSリソースを直接繋ぐ仕組み – バックエンドのリソースファイル保存に応じて、 即時でAWSへ環境構築。 – 複数人でも、それぞれ専用の環境が構築される。 – AWS CDK のホットスワッピングを使い、高速デプロイ。 -
DEEP DIVE IN CODE TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai
/ Amplify Gen2 Deep Dive 13 -
今回の流れ ▪ ターゲット – Data リソース (amplify/data/resource.ts) ▪ フィールド・モデル・スキーマの型 ▪
フロントエンドへの型連携 ▪ Sandbox での CDK 実行 TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 14 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 16 “ModelField” がフィールドの型 amplify/data/resource.ts Fields -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 17 resource.ts で string() をフィールドに設定。 ModelField.ts に string() の定義がある。 実際は _field() メソッドを返す。 node_modules/@aws-amplify/data-schema/src/ModelField.ts Fields -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 18 _field() の中で、require() などの メソッドが定義されている。 メソッド自体の戻り値の型は “ModelField”。 node_modules/@aws-amplify/data-schema/src/ModelField.ts Fields -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 19 ModelField 型の中で、チェインさせるメソッ ドの型定義。 require() は, “UsedMethod” と “required” のユニ オン型を使って自身を再度呼ぶ。 Omit によりメソッドチェインの制御。 node_modules/@aws-amplify/data-schema/src/ModelField.ts Fields -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 20 model() メソッドは “ModelType” 型。 amplify/data/resource.ts Models -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 21 resource.ts で model() を利用。 ModelType.ts に model() の定義がある。 実際は _model() メソッドを返す。 node_modules/@aws-amplify/data-schema/src/ModelType.ts Models -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 22 _model() メソッドの戻り値の型は “ModelType”。 fields に、フィールドが格納される。 node_modules/@aws-amplify/data-schema/src/ModelType.ts Models -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 23 ModelType 型の中で、チェインさせるメソッ ドのの型定義。 ModelField 型と同様に、チェインさせる メソッドは、 “UsedMethod” と Omit を使って 制御。 node_modules/@aws-amplify/data-schema/src/ModelType.ts Models -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 24 schema() メソッドのは “ModelSchema” 型。 amplify/data/resource.ts Schema -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 25 resource.ts で schema() メソッドを利用。 ModelSchema.ts に schema() メソッドの定義 がある。 実際は bindConfigToSchema() が呼ばれる。 node_modules/@aws-amplify/data-schema/src/ModelSchema.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 26 bindConfigToSchema() メソッドは “SchemaReturnType” 型を返す。 “SchemaReturnType” の実際の型は “ModelSchema” 型。 node_modules/@aws-amplify/data-schema/src/ModelSchema.ts Schema -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 27 ”ModelSchema” 型の中で、チェインさせる メソッドの型定義。 “ModelField”と同様に、“UsedMethod” と Omit を使って制御。 node_modules/@aws-amplify/data-schema/src/ModelSchema.ts Schema -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 28 bindConfigToSchema() を再度確認。 _ddbSchema() メソッドを呼び出している。 (DynamoDB利用の場合) node_modules/@aws-amplify/data-schema/src/ModelSchema.ts Schema -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 29 schema() の返すオブジェクトの生成。 models フィールドの中に、 モデル(今回だと “Todo”)が格納される。 node_modules/@aws-amplify/data-schema/src/ModelSchema.ts Schema -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 30 ModelSchema ModelType ModelField models: fields: string() integer() … -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 32 フロントエンドからは Schema 型を使う。 これは、 “resource.ts” に定義。 “Todo” は、自分で宣言したモデル。 “type” はどこから? “ClientSchema” 型を確認。 amplify/data/resource.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 33 型引数 “Schema” は、先に見た通り “ModelSchema” 型。 “ModelSchema” と “GenericModelSchema” は 要素が同じになるため、実際の型として “InternalClientSchema” が選択される。 node_modules/@aws-amplify/data-schema/src/ClientSchema/index.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 34 “InternalClientSchema” の型引数 “CustomerSchema” は “ModelSchema”。 そして、“ModelSchemaContents” でもある。 そのため、プロパティの型として “ClientSchemaProperty” を選択。. node_modules/@aws-amplify/data-schema/src/ClientSchema/index.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 35 型引数 “T” は “ModelSchema”。 つまり “T[K]” スキーマの持つ要素になるので、 “ModelType” となる。 そのため、 “RemapModel” 型が選択される。 node_modules/@aws-amplify/data-schema/src/ClientSchema/index.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 36 型引数 “E” が “ModelType” として 呼ばれている。 そのため、 “ClientModel” 型が選ばれる。 node_modules/@aws-amplify/data-schema/src/ClientSchema/index.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 37 “ClientModel” 型の中に、最初にフロントエン ドで使っていた “type” プロパティが出てきた。 値の型は、 “ClientFields” 型であり、 さらに中を見ると “ResolveFields” 型。 node_modules/@aws-amplify/data-schema/src/ClientSchema/Core/ClientModel.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 38 “ResolveFields” 型で、プロパティの名前と 値のチェック。 ここは、Nullableでもそうでなくても同じ型 “ResolveIndividualField” が使われる。 node_modules/@aws-amplify/data-schema/src/ClientSchema/utilities/ResolveField.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 39 “ResolveIndividualField” の中で、型引数 “T” が “BaseModelField” 型かの確認。 これは、フィールドの値として呼ばれている ので、 “ModelField” 型であるはず。 node_modules/@aws-amplify/data-schema/src/ClientSchema/utilities/ResolveField.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 40 “BaseModelField” 型の中を見ると、 “ModelField” 型が実体となっている。 node_modules/@aws-amplify/data-schema/src/ModelField.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 41 “type” の中に、 “ModelField” が連携される。 →タイプ・ヒンティングで 宣言内容が出てくる。 amplify/data/resource.ts -
Sandbox での CDK 実行 TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai
/ Amplify Gen2 Deep Dive 42 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 43 “ampx” コマンドは “yargs” パッケージを利用。 引数の解釈・実行はそれに準じている。 まずは “createMainParser” メソッドの確認。 packages/cli/src/ampx.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 44 Sandbox のコマンド定義のみ取り上げる。 “createSandboxCommand” メソッド確認。 packages/cli/src/main_parser_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 45 コードのポイントが二つ。 yargs のための “コマンド実行の定義” と “CDK 実行の定義”。 packages/cli/src/commands/sandbox/sandbox_command_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 46 “SandboxSingletonFactory” が “CDK 実行の定義”。 packages/cli/src/commands/sandbox/sandbox_command_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 47 “SandboxCommand” が “コマンド実行の定義”。 まずはこちらから。 packages/cli/src/commands/sandbox/sandbox_command_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 48 “SandboxCommand” は “yargs” のための定義。 呼び出し時のコマンド “npx ampx sandbox” の 引数 “sandbox” が “this.command = ‘sandbox‘“ に一致するとこのオブジェクトが 実行される。 packages/cli/src/commands/sandbox/sandbox_command.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 49 “yargs” が “handler” メソッドを呼び出す。 “handler” の中で “sandbox.start()” をさらに呼び出し。 “sandbox” はコンストラクタの第一引数。 packages/cli/src/commands/sandbox/sandbox_command.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 50 “createSandboxCommand” を再確認。 第一引数の “sandboxFacory” は “SandboxSingletonFactory”。 二つ目のポイントの “CDK 実行の定義”。 packages/cli/src/commands/sandbox/sandbox_command_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 51 “SandboxSingletonFactory” の処理の実体は “getInstance()” メソッド。 その中で “FileWatchingSandbox” を 呼んでいる。 packages/sandbox/src/sandbox_singleton_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 52 “FileWatchingSandbox” の中の “start” メソッ ドが、 “SandboxCommand” の中で呼んでい た “sandbox.start()” の実体。 packages/sandbox/src/file_watching_sandbox.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 53 “start()” メソッドを追うと、内部で “deployAndWatch()” を呼んでいる。 packages/sandbox/src/file_watching_sandbox.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 54 “deployAndWatch()” メソッドは、 さらに “this.deploy()” メソッドを呼ぶ。 packages/sandbox/src/file_watching_sandbox.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 55 “this.deploy()” メソッドは、さらに “this.executor.deploy()” メソッドを呼ぶ。 packages/sandbox/src/file_watching_sandbox.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 56 “this.executor” は “FileWatchingSandbox” の 第二引数。 packages/sandbox/src/file_watching_sandbox.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 57 “SandboxSingletonFactory” で引数の確認。 第二引数は “AmplifySandboxExecutor” クラス。 packages/sandbox/src/sandbox_singleton_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 58 packages/sandbox/src/sandbox_executor.ts “AmplifySandboxExecutor” の “deploy()” メソッドが、 “FileWatchingSandbox” の “this.executor.deploy()” として呼ばれている。 その中で、 “this.backendDeployer.deploy()” を呼んでいる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 59 packages/sandbox/src/sandbox_executor.ts “this.backendDeployer” は コンストラクタの第一引数。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 60 “SandboxSingletonFactory” で引数の確認。 “AmplifySandboxExecutor” の第一引数は、 “BackendDeployerFactory” クラス。 packages/sandbox/src/sandbox_singleton_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 61 packages/backend-deployer/src/cdk_deployer_singleton_factory.ts “BackendDeployerFactory” の実際の処理は “getInstance()” メソッド。 この中で “CDKDeployer” クラスを呼んでいる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 62 packages/backend-deployer/src/cdk_deployer.ts “CDKDeployer” クラスの “deploy()” メソッドが、 “AmplifySandboxExecutor” の “this.backendDeployer.deploy()” として 呼ばれる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 63 packages/backend-deployer/src/cdk_deployer.ts この “deploy()” メソッドの処理を追うと、 さ らに “this.tryInvokeCdk()” を呼んでいる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 64 packages/backend-deployer/src/cdk_deployer.ts “this.tryInvokeCdk()” メソッドを追うと、 さらに “this.invokeCdk()” メソッドを 呼んでいる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 65 packages/backend-deployer/src/cdk_deployer.ts “this.invokeCdk” メソッドを追うと、 “this.executeCommand()” を呼んでいる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 66 packages/backend-deployer/src/cdk_deployer.ts そして、 “this.executeCommand” メソッドを 確認すると、 “this.packageManagerController.runWithPacka geManager()” メソッドを呼んでいる。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 67 packages/backend-deployer/src/cdk_deployer.ts “this.packageManagerController” は、 “CDKDeployer” のコンストラクタの第三引数。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 68 packages/backend-deployer/src/cdk_deployer_singleton_factory.ts “BackendDeployerFactory” に戻って確認。 “CDKDeployer“ の第三引数は、 ベースクラスのコンストラクタの第一引数. “packageManagerController”。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 69 さらに “SandboxSingletonFactory” へ 戻って確認。 “BackendDeployerFactory“ の第一引数は “PackageManagerControllerFactory” クラス。 packages/sandbox/src/sandbox_singleton_factory.ts -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 70 packages/cli-core/src/package-manager-controller/package_manager_controller_factory.ts “PackageManagerControllerFactory” クラスの処理 の実体は “getPackageManagerController()” メソッド。 ここではパッケージマネージャーに “NPM” を使う 前提で “NpmPackageMnagerController” を確認。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 71 packages/cli-core/src/package-manager-controller/npm_package_manager_controller.ts “NpmPackageManagerController” はコンスト ラクタで super() を呼ぶだけ。 親クラスの “PackageManagerControllerBase” を続けて確認。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 72 packages/cli-core/src/package-manager-controller/package_manager_controller_base.ts “PackageManagerControllerBase” の中で、 “CDKDeployer” で呼んでいた “runWithPackageManager” を発見。 さらに、 “this. executeWithDebugLogger” が 呼ばれている。 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 73 packages/cli-core/src/package-manager-controller/execute_with_debugger_logger.ts 最終的に、 “execa” パッケージを使った 処理を発見。 ここでコマンドとしての “CDK” を実行。 -
バックエンドリソースと フロントエンド・リソースの連携 (再) TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai /
Amplify Gen2 Deep Dive 74 -
まとめ ▪ バックグラウンドのリソースファイル(i.e. “amplify/data/resource.ts”) が、 フロントエンドの型として連携されることの確認。 – TypeScript の型定義を駆使してできている。 ▪
ampx コマンド経由で Sandbox を有効にし、 リソースファイルの更新に応じてAWS CDKコマンドを実行していることを確認。 ▪ これらの仕組みがによって、AWS Amplifyでの開発者体験が 格段に向上した。 TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 75 -
TSKaigi Kansai 2024 / #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep
Dive 76 Amplify TypeScript -
Amplify Japan User Group AWS Amplify に関する情報発信・ミートアップを開催 TSKaigi Kansai 2024
/ #TSKaigi #TSKaigiKansai / Amplify Gen2 Deep Dive 77 Disocrd はこちらから参加!! https://aws-amplify-jp.github.io/ -
Amplify Boostup #7 2024/12/19 東京+オンライン TSKaigi Kansai 2024 / #TSKaigi
#TSKaigiKansai / Amplify Gen2 Deep Dive 78 https://aws-amplify-jp.connpass.com/event/334686/