RuntimeでサーバーレスDartしてみたAWSDartlambdaserverless最近Dartに興味を持ってきたので今回はDartの話をします。今までDartはkotlinやscalaと比べてイケてないという評判を聞いて食わず嫌いしていたのですが、Flutterに採用されてから盛り返してるっぽいのを見てお盆休みで時間もあるしロゴもかっこいいしちょっと触って見ようかなと思ったのでLambdaで動くようにしてみました。最終的な成果物はこちらにおいてあります。デプロイしてみるではとりあえずこの自作ランタイムを使うときの流れを見ていきます。デプロイに必要な物は以下の通りです。Frameworkdockerまずserverless.ymlです。Frameworkがわかる方にはほとんど説明不要だとは思います。使ったことが無い方へ説明をするとfunctionsがLambdaを定義している箇所で、それぞれhelloをハンドラーとしてgetリクエストを<url>/helloで受け付けるLambdaファンクションhelloとworldをハンドラーとしてpostリクエストを<url>/worldで受け付けるLambdaファンクションworldが定義されています。次にここでハンドラーとして指定されているhelloとworldを見ていきます。src/handlerの中にそれぞれhello.dartとworld.dartというファイルを用意しています。'新たな光に会いに行こう。lambdaHandler(hello);}getに対して適当なメッセージを返却するコードです。lambdaHandlerが今回自作したランタイムでlambdが呼び出されたときにhelloを実行するようにしています。lambdaHandler(world);}こちらもほぼ同じです。postで入ってきたbodyをそのまま返しています。それではこれらをデプロイするための簡単なスクリプトを用意してあるので実行してみましょう。問題無くデプロイされれば以下のような画面が出てくるはずです。None(略)それぞれ正しくデプロイできていれば以下のようなレスポンスが帰ってくるはずです。https://hoge.execute-api.ap-northeast-1.amazonaws.com/dev/hello{"msg":"新たな光に会いに行こう。\https://hoge.execute-api.ap-northeast-1.amazonaws.com/dev/world[{"name":"島村卯月"},{"name":"渋谷凛"},{"name":"本田未央"}]中身を見てみようLambdaで動かすためのランタイムの中身をもう少し詳しく見ていきましょう。runtimeで任意のLambdaを動かすのに必要なことは大きく2つです。runtimeに設定したときに起動時に最初に実行されるファイルbootstrapの用意まず無限ループの方から見ていきます。今回はルートディレクトリにruntime.dartというファイルを用意しています。}}あまり難しいことはしていませんが一通り見ていきます。http://${Platform.environment['AWS_LAMBDA_RUNTIME_API']}/2018-06-01/runtime/invocation/nextを叩くことでLambdaへのリクエストの各種情報とリクエストIDが取得できます。これをこの関数の引数のcallbackに処理をさせ、その結果をそのままhttp://${Platform.environment['AWS_LAMBDA_RUNTIME_API']}/2018-06-01/runtime/invocation/${request_id}/responseに引き渡すことで結果を返却することができます。次にbootstrapです。先程デプロイしたままであればルートディレクトリにこのようなファイルがあるはずです。$bin_dir/$_HANDLER.dart.aot.aotというディレクトリにaotのランタイムとコンパイルした結果を設置してありlambdaが起動したときにそれをそのまま実行するようになっています。このbootstrapや.aotの中身を用意しているので先程使用したdeploy.shなのですが、この中身はこんな感じになってます。$stg一つずつ見ていきましょう。$bin_dirまずコンパイル結果を置く場所や元のハンドラー場所を設定し、前回のデプロイ時作ったファイル類を掃除してます。1実行に必要なbootstrapを生成しています。別にbootstrapはわざわざ毎回生成する必要は本来無いのですが、既存のプロジェクトへの組み込みやすさ等を考えて今回はここで生成するようにしてしまいました。1ここでdart側の事前準備をしています。dartのdokcerイメージからlinux向けのaotの実行ランタイムをとって来ていますがこれはmacを考慮してそうしているだけでlinuxな環境ならローカルにある物をそのまま持ってきても問題無く動作します。ここはもっと色々な物を一緒に詰めてやる必要があるかな?っと思ってたのですがlayerとかで頑張って用意する必要もなくあっさり動いてしまいました。$stg最後に各ハンドラーをコンパイルしてデプロイしています。grepやawkでガチャガチャやってますがこれでハンドラーに指定している名前を引っ張りだしてコンパイルしています。$2}'helloworldまたデプロイ時にステージを選択するオプションに引数を渡していますがこれはこのスクリプトに渡す引数をそのまま横流し、無いならdevになるようにしています。stg="dev"Q.仕組みとかよくわかんねぇけどとりあえず既存のプロジェクトに組み込みてぇんだけどどうすればいいのさ?そういった声にお答えしてこんな感じにやればいいんじゃねって感じの手順を用意しました。筆者はFlutter等の実践的なフロントやアプリのDartの経験があるわけでは無く、動作は保証しかねるのであしからず。お好きなところにruntime.dartとハンドラーを置いておくディレクトリを用意runtime.dartはハンドラーから読めれば良いのでそれぞれのプロジェクトにとって適切な場所に置いておいてください。ハンドラーを置くディレクトリもデフォルトではsrc/handlerとしていますが簡単に変更出来るのでこれも適切な場所に用意してください。このデプロイスクリプトではハンドラーのディレクトリに更を階層分けるような構造には対応していないので注意してください。deploy.shの修正もし3でハンドラー置き場等を変更していたりする場合にはここの変数を修正します。handler_dir="./src/handler"bin_dir="./.aot"handler_dirがハンドラー置き場なので好きに変更しましょう。コンパイル結果を置く場所もここで変更できます。デプロイ実行これで実行すればデプロイされるはずです。Dartはシングルバイナリを吐くタイプの言語では無いのでCrystalなどに比べて正直もっと苦戦すると思ってたのですが思いの外あっさり動きましたね。あと今回始めてDartを触ってみて思ったのですが、vscodeの拡張の出来がいいのか思ってたより開発しやすかったです。ロゴが好きなので触っただけだったので実績だけ作って終わりでもいいかなって感じで始めたけどこれならしばらくは個人で開発するLambdaはDartにしてもいいかもしれないですね。2020/1/6追記dart2native対応版出しました。業界最多のコンテンツラインナップとともに最新のテクノロジーを駆使した各種ソリューションを出版社や電子書店に提供し、グローバル且つマルチコンテンツ配信プラットフォームを目指しています。upLoginユーザーは見つかりませんでした。