カテゴリー: programming

Route53 で S3 バケットへ alias レコードを作った際のリダイレクトのふるまい

 Amazon S3 は、全てのリクエストをリダイレクトや、パスに応じたリダイレクトを設定できる機能を持っています。これは Static Web Hosting という設定を入れることにより実現可能です。実際の技術詳細については以下の公式ドキュメントを参照してください。

  • 公式ドキュメント: https://docs.aws.amazon.com/AmazonS3/latest/dev/how-to-page-redirect.html

リダイレクト設定

gochiusa.53ningen.com に対して gochiusa.com へのリダイレクト設定作業は以下の 3 STEP です

  1. S3 バケットを gochiusa.53ningen.com という名前で作成する
  2. Static Web Hosting 機能を有効にして、すべてのリクエストを gochiusa.com にリダイレクトする設定を入れる
  3. Route 53 に gochiusa.53ningen.com に対して先ほど作ったバケットへのエイリアスを張る A レコードを作成する

動作確認

作業後、設定を dig で確認します

解決される 52.219.68.26 は S3 の静的配信サーバーの IP の模様で、振る舞い的には Host ヘッダと同じ名前を持つ S3 バケットへリダイレクトをかけるという形のようです。それを確認するために次のようなリクエストを送ってみます。

x-amz-error-message: Request does not contain a bucket name. というメッセージからわかるようにバケットネームの指定がないというエラーで AWS S3 のトップページに飛ばされます。次に Host ヘッダをつけるとどうなるか試してみましょう。

The specified bucket does not exist というエラーメッセージに変わりました。ではそろそろ真面目に先ほど作った gochiusa.53ningen.com という値を Host ヘッダにつけて叩いてみましょう。

正常に 301 で http://gochiusa.com/ にリダイレクトされていることが確認できました。

実験からわかること

  1. S3 バケットへの alias レコードセットの制約の理由が推測できる
    • Route53 で S3 static web hosting しているバケットに alias を張る際は、公式ドキュメントに記載されているように Record Set の Name と S3 バケット名が一致している必要がある
    • これは Host ヘッダをみて、対象の S3 静的配信コンテンツへのリダイレクトを行なっている仕組みから生まれる制約だろうということが、上記の実験から分かる
  2. S3 バケットへの alias を張っているドメインを指す CNAME を張ると正常に動作しない
    • 実際に gochiusa2.53ningen.com に対して gochiusa.53ningen.com を指すような CNAME レコードセットを作ると以下のような実験結果になる

php 7.x の configure オプション

ただコマンドをうっただけ(自分用メモ)

Xamarin.iOSでのストーリーボードを使わない開発

 Visual Studio で Xamarin.iOS のプロジェクトを作成すると、ストーリーボードなどという忌まわしいものがデフォルトで作成されてしまい非常に厳しい気持ちになります。この記事では、それらを削除して、コードでUIを構成していくためのステップを説明します。3分ほど作業をすれば邪魔なものが消えてなくなってくれます。

1. Main.storyboard を削除

2. ViewController.designer.cs を削除

3. ViewController の余計なコードを削除する

ViewController が partial class である必要がなくなったので、partial キーワードを消します。合わせて IntPtr を引数にとるコンストラクタも不要になりました。

4. Info.plist の Main Interface を削除

5. AppDelegate に ViewController を表示するコードを追加

6. 動くサンプル

GitHub で公開しているので適当にどうぞ: https://github.com/pawotter/Xamarin.iOS.NonStoryboard

MySQL スロークエリログを fluentd 経由で elasticsearch に流し込む

MySQL のスロークエリログを fluentd で elasticsearch に流し込む流れをメモ。基本は以下のステップ。

  1. my.conf のスロークエリログ出力設定をして mysql restart
  2. fluent-plugin-mysqlslowquery を導入
  3. ログを elasticsearch に流し込む fluentd の conf を書いて td-agent restart

1. MySQL のスロークエリログ出力設定

  • docs: https://dev.mysql.com/doc/refman/5.6/ja/slow-query-log.html
  • 以下を追加して MySQL を restart すれば OK
  • 起動中の場合は set global で対応できる(restart しないでもOK)

2. fluent-plugin-mysqlslowquery の導入

  • repository: https://github.com/yuku-t/fluent-plugin-mysqlslowquery
  • 以下のような具合でおしまい

3. td-agent の conf 作成

  • 送信側

DelegatingHandlerを用いた快適なiOSアプリのHTTP通信周辺環境の整備

 昨今のネイティブクライアントアプリで、 HTTP 通信を行わないものはないと言っても過言ではないくらい、アプリ開発の基本中の基本だと思います。きっと、開発を行う中で HTTP 通信の前後に色々な処理を挟んでみたいという気持ちが湧いてくるのではないでしょうか。たとえば以下のような話です。

  1. リクエストの内容をログ出力したい
  2. 電波状況が悪いときはリクエストを走らせないようにしたい
  3. 通信中はネットワークアクティビティインジケータを走らせたい

 そんなときに System.Net.Http.DelegatingHandler はとても便利な代物です。公式のドキュメントはこちら: https://msdn.microsoft.com/ja-jp/library/system.net.http.delegatinghandler(v=vs.110).aspx

1. HTTP リクエストのログ出力

 たとえば、Http リクエストの内容をログ出力したいとすれば、以下のような簡単な DelegatingHandler のサブクラスを作ってあげるとよいでしょう。

 実用的には Console.WriteLine をクリティカルセクションに配置したほうが良いかもしれませんが、ひとまずこのような単純なコードでリクエストの手前に処理を挟むことができました。使い方は、単純にこれを System.Net.Http.HttpClient のコンストラクタに渡すだけです。これで全てのリクエストの内容がログ出力されます。

2. 圏外時にリクエストを送らない

Reachability を使えば簡単です。

3. 通信中にネットワークアクティビティインジケータを回す

 ネットワークアクティビティインジケータの管理、非常にめんどうですよね。通信が同時に複数走るのはザラなので、そのあたりを考慮する必要があると思います。だいたい皆さん同じような実装をすると思うのですが、今走っている通信の数が正であれば、インジケータを回しっぱなしにして、0になったら止めるみたいなカウンターを作るのではないかなと思います。ひとまずステップをわけて実装を見ていきます。

3.1. NetworkActivityIndicator の抽象化

 ネットワークアクティビティマネージャは基本的に ON/OFF のインターフェースさえ持っていれば十分でしょう。それぞれActivate(), Inactivate() という名前のメソッドとします。実装クラスは、UIApplication インスタンスを外から受け取り、Activate(), Inactivate() のタイミングで NetworkActivityIndicatorVisible の値に true, false をぶち込んであげれば良いという話になります。

3.2. 走っているリクエストをカウントするクラスの作成

 同時に走っているリクエストが1つ以上ある場合に IIndicatorActivate() を呼び出し、通信が走っていない状態になるとき Inactivate() を呼び出す簡単なカウンタークラスを作りましょう。

 このカウンタークラスは、通信開始時には Attach()、 終了時には Detach() を呼ぶ簡単なインターフェースを持つことになるでしょう。それぞれインターフェースと実装コードは以下のようになると思います。

3.3. DelegatingHandler の実装

 準備ができたので、今まで作ったものを利用してネットワークアクティビティインジケータを通信が走っているときにクルクルまわす DelegatingHandler を実装しましょう。以下のようになります。

 コード全体を GitHub で公開しているので使いたい方はどうぞ。MITライセンスです。 Xamarin.iOSに依存するパッケージの nuget への放流方法イマイチよくわからんので有識者の方、教えていただけると嬉しいです

  • Repository: https://github.com/pawotter/NetworkActivityManager

3.4. Swift での実現方法

 URLSessionラップして、自分で HttpClient 作ればできるよ。実装はだいたい同じ。実装的にもパフォーマンス的にも改善の余地があるコードですが、わかりやすく伝えるとするならば以下のような実装コードになる気がします。

5. おわりに

DelegatingHandler ベンリすぎワロタ。あとこれを使うとリトライ処理とかも挟めてとってもベンリ&ベンリです。良いですね〜。

Route53へのDNSとドメインの移行

次のものを AWS に移行しました。

  • ドメイン移管(53ningen.com): ムームードメインから Route 53 へ
  • ドメインネームサーバー移行: ムームードメインから Route 53 へ

また、もとの運用では存在しなかった、次のようなものを導入しました。

  • L7レイヤーでのヘルスチェック
  • DNSフェイルオーバー

この資料は自分向けの作業ログであるため、実際には各ステップ冒頭に記された公式ドキュメントを理解した上で読むことを強く推奨します。

手元環境

 作業は基本的には terraform を使って行いました。ただし、ドメインの移管に関しては Route 53 のマネジメントコンソールとムームードメインのコントロールパネルを操作する必要があります。

1. DNS を Route 53 へ移行

 ドメインも Route 53 に移管しますが、その際に元のレジストラ(ムームードメイン)が提供するネームサーバーからドメインが削除されてしまうので、前もって DNS を Route 53 に切り替えておきます。

1.1. ホストゾーン(Hosted Zone)の作成

公式ドキュメント: 既存ドメインの DNS サービスを Amazon Route 53 に移行する

 ホストゾーンとはドメインに紐づくリソースレコードのセットです。おおよそゾーンファイルと対応していると考えて良いと思います。実際にゾーンファイルを取り込むこともできるようです(公式ドキュメント: ゾーンファイルをインポートしてリソースレコードセットを作成する)。

 ホストゾーンには、パブリックなものとVPC向けのプライベートなものがあります。マネジメントコンソールからドメイン名を入力すれば作成が完了しますが、今回はこのリソースを terraform で管理します。

terraform plan は以下のとおり

 terraform apply してホストゾーンを作成すると SOA レコードNS レコード も自動的に作成されます。今回はドメイン名とIPアドレスを紐づけるために A レコード の追加が必要になります。そのため、その記述を追加します。メールサーバーの移行が必要であれば MX レコード、サブドメインなどの運用をやっているのであれば CNAME レコード など適当な感じに必要なものも移行しておきましょう。ひとまず今回は A レコード のみを作ります(Route 53 が対応しているDNSリソースは サポートされる DNS リソースレコードタイプ を参照)。terraform apply を実行するとレコードが作成されます。

1.2. DNSの変更

 マネジメントコンソールの NS レコード欄の DNS サーバーを、ムームードメインのコントロールパネルで指定します。反映が有効になるまで少し時間がかかるため、少し待って dig で確認すると良いとおもいます。

1.3. コストの計算

公式ドキュメント: 料金

 お仕事ならこの計算作業する前にやるべきですが、個人のお遊びサーバーなので作業後に計算しました。

  • ホストゾーン
    • 0.50 USD(ホストゾーンごと)/月 – 最初の25のホストゾーン
    • 0.10 USD(ホストゾーンごと)/月 – それ以上のホストゾーン
  • 標準的クエリ
    • 0.400 USD(100 万クエリごと) – 最初の 10 億クエリ/月
    • 0.200 USD(100 万クエリごと) – 10 億クエリ以上/月

おおよそ 1ホストゾーン + 最初の10億クエリ = 0.50 + 0.40 = 0.90 USD

1.4. ヘルスチェックの設定 (Optional)

公式ドキュメント: Amazon Route 53 ヘルスチェックの作成と DNS フェイルオーバーの設定

 ヘルスチェック(L7)とDNSフェイルオーバーが利用できます。ヘルスチェックで障害を検知した場合に Cloudwatch Alarm と連携をさせたり、DNSフェイルオーバーを利用して待機系に参照を向けたりすることが可能です。

 ひとまずベーシックなウェブサーバーのヘルスチェックは以下のように設定できます。その他諸々 terraform を利用する際にオプション記述については terraform 公式ドキュメント: aws_route53_health_check を参照してください。

ヘルスチェックに関しては、

  • AWSエンドポイント
    • ヘルスチェック 1 件につき 0.50 USD*/月
    • オプション機能 1 件につき 1.00 USD/月
  • AWS以外のエンドポイント:
    • ヘルスチェック 1 件につき 0.75 USD*/月
    • オプション機能 1 件につき 2.00 USD/月
  • 任意のヘルスチェック機能は以下の通りです。
    • HTTPS
    • 文字列マッチング
    • 短インターバル
    • レイテンシー計測

となっています。

「AWS エンドポイント」とは、AWS の中で稼働するリソース(たとえば Amazon EC2 インスタンス)のうち、ヘルスチェックと同じ AWS アカウントの中でプロビジョニングされるか、ヘルスチェックと同じアカウントが請求先となっているものを指します。計算済みヘルスチェックとメトリクスベースのヘルスチェックは AWS エンドポイントのヘルスチェックとして請求されます。Elastic Load Balancing のリソースまたは Amazon S3 ウェブサイトバケットがエンドポイントであるヘルスチェックについては、お客様への請求は発生しません。Elastic Load Balancing のリソースおよび Amazon S3 ウェブサイトバケットをエンドポイントとするヘルスチェックについては、AWS によって自動的にプロビジョニングされ、Amazon Route 53 の一部として追加料金なしでご利用いただけます。

1.5 DNSフェイルオーバーの設定 (Optional)

公式ドキュメント: DNS フェイルオーバーの設定
terraform 公式ドキュメント: aws_route53_record

 ヘルスチェックを入れたついでに、障害発生時に S3 の静的ホスティング機能 + Cloudfront によるメンテナンスページのほうへ参照を向けるようなDNSフェイルオーバー設定を入れてみます。DNSフェイルオーバー設定については無料で利用することができます。最終的な構成図は以下のような形になります。


 
 ディザスタリカバリを想定した構成として、ap-northeast-1 リージョンで稼働させるアプリケーションサーバーに対して、メンテナンスページを静的ホスティングする際の S3 リージョンは地理・物理的に違う系統の適当なリージョンを選択します。今回は us-east-1 を選択しました。

 S3 の前段に置いた Cloudfront は主に S3 からの配信をキャッシュする役割と、メンテナンスを表すステータスコード 503 でリソースを返す役割を持っています。S3 バケットの作成とファイルの配置、静的ホスティング機能の有効化および Cloudfront の設定は以下のように terraform で記述することができます。

terraform 公式ドキュメント: aws_s3_bucket
terraform 公式ドキュメント: aws_cloudfront_distribution

resources/error には、適当なメンテナンス表示 html ファイルを、 policies/maintenance.53ningen.com_s3_policy.json には以下のようにバケットのファイルの読み取りを許可するポリシーを配置します。

つづいて Route 53 ホストゾーンにフェイルオーバーの設定をします。通常時は既存の A レコードが有効になるようにしつつ、ヘルスチェックに失敗した場合にメンテナンスページを静的にホスティングしている S3 のほうに参照を向けるような設定を入れます。また ttl を最初の設定より短く 60 秒に変更します。 terraform を用いて次のように記述できます。

 最後に動作確認として、動いているウェブサーバーを停止し、きちんとメンテナンス表示に切り替わるか確認します。またウェブサーバーを起動したときに、ヘルスチェックが通るようになり、きちんとアプリケーションサーバーに参照が戻るかも合わせてチェックしておきましょう。

2. ドメインを Route 53 に移管する

公式ドキュメント: ドメインの移管

ムームードメインで購入した 53ningen.com ドメインを Route 53 に移管します。ステップとしては以下のとおりです。

  1. WHOIS 情報としてレジストラの情報を代理公開している場合は、ムームードメインのコントロールパネルから自分のものに変更する
  2. 確認のメールが飛んでくるので踏む
  3. AUTH_CODE をメモ
  4. Route 53 の Domain registration から Transfer Domain to Route 53 に進みドメイン名を入力
  5. AUTH_CODE を入力
  6. 移管後のDNSとして先ほど作った Route 53 の Hosted Zone を指定する
  7. AWSから移管確認のメールが飛んでくるので踏む
  8. そのうち移管が完了する

Waiting for the current registrar to complete the transfer (step 7 of 14)
ドメインが移管の要件を満たしているか現在のレジストラが確認しています。このステップは、ドメインの TLD に応じて最大 10 日かかる場合があります。

結構待ったりいろんな確認メールのリンクを踏んだりする必要がありますが、あまりテクニカルな手順はないはず…。

iOSDC Japan 2017にてベストトーク賞をいただきました

 2017/09/15〜17 の 3日間にわたって開催されたカンファレンス iOSDC Japan 2017 に参加してきました。私は2日目の 14:20〜14:50 に Track A 会場にて「RxSwift の Observable とは何か」というタイトルでセッションを持たせていただきました。

 このまわりの話をちゃんと解説しようとすると、最低でも60分は必要かなと思っていたのですが、最長の枠が30分しかなかったのでやむなしで CfP を提出しました。発表内容については以前からコードを追っかけてた分野だったので改めてする作業もそんなになく(とか思ってたんですが、以前に真面目にコードリーディングしたSwift1.2/2.x時代と比較してかったるい diff とかがあって地味に胃が痛かった)、スライドとか口頭発表原稿とかを書き起こす程度でした。ただ当時の自分は頭がおかしかったようでスライドを Illustrator + In Design で作り始めてしまい、次回から素直にパワポで作ろうと思いました(細かいレイアウトを指定できるのはいいけどめんどくさかった)。

 お話の構成をするなかで、300lines近くの実装コード解説をどうやったら、スライドとトークの内容で聴いていただく皆さまに理解してもらえるかをだいぶ悩みました。ただでさえ、発表のスライドにコードがあるとウッとなるはずなのに、それを30分間ひたすらやり続けたら、地獄でしかないので、この部分をクリアする点に力を注ぎました。そこで、ベースとなるソースコードを頭のスタック領域に置いていただくための説明に発表の半分以上の時間かけて、その上で、Reactive Extensions 特有の diff を解説するというトーク構成にしようと決めました(発表の7日くらい前に)。

 実際発表のリハーサル的なものを自分一人でやってみたんですが、どうやっても45分くらいかかってしまい、泣く泣くスライドのタイトルに(余談)という文字列を入れて、口頭発表の内容からは削ったりしました。来年から45分枠とかほしい…。

 今回のお話は決して技術的レベルの高い話ではなくて、まとめてしまうと有名な設計パターンとその発展形についてのお話でした。他の方のセッションをいくつか拝聴させていただいたのですが、私よりも技術的にはるかにハイレベルなことをやっていたり、普段自分が無意識にやっていてわりと共感できるようなお話がいくつもあって楽しかったです。

 特に面白かったセッションは @k_katsumi さんの Building High Performance and Testable UI component で、自分が普段 iOS のプレゼンテーション層を書くときの考え方とだいぶ近くて非常に共感できました。自分のやっている方法を自分自身でしっかり論理的根拠を持ってある程度正しそうという気持ちを持てるようにできるのが一番いいですが、やっぱり似たような手法を他の方もやられているという話を聞くと気持ち的には安心できますね…。

 あとは @kitasuke さんの Introducing protobuf in Swiftのあとに、Ask the speaker まわりで protobuf vs swagger みたいな話ができて楽しかった。サーバー〜モバイルクライアント間での protobuf 利用がどのようにされているのかの事例、ちゃんときいたことがなかったので興味深かった。あと protobuf とエラーハンドリングまわりの話も大変参考になった。最後には、結局APIクライアントを人間が書くことを撲滅していきましょうみたいな気持ちをみなさんと共有できたところがよかったですね…。撲滅していきましょう。

 素晴らしいセッションがたくさんある中、私の稚拙な発表を聴いていただいた皆さま、運営スタッフのみなさまなど本当にありがとうございました。そしてまさか自分がベストトーク賞をいただけるとは本当に思っていなかったので、LT枠の無限ビールタイムの時間にビール4本飲んでいい感じに意識があいまいになっていました。粗相してなかったですか?大丈夫ですか?

 ベストトーク賞の商品としてサイバーエージェントさんから素晴らしいお品をいただけるようで本当にありがとうございます。アベマTVさん最高のサービスです。アメーバブログさんでよく声優さんのブログ記事と写真を見ています。最高のサービスです。いただいたディスプレイでアベマTVさんとアメーバブログさんを見ます!

アメーバブログさんで特に見ているのは以下のブログです

アメーバブログさん最高のサービスです。私も声優さんのブログになりたい。

 2日目の発表が終わったあと、残念ながら Wake Up, Girls! 4th Live Tour 東京公演 夜の部がイベ被りしており、懇親会には参加できませんでしたが、来年 Wake Up, Girls! のイベントが被っていなければ懇親会に参加したいなと思います。ハッシュタグ見てたら美味しそうな料理と充実したクラフトビールとハイレベルなエンジニアがたくさんいてとても楽しそうだった。私、ビール(詳しくはないのですが)大好きなので、スポンサーの転職ドラフトさん来年も無限ビールお願いします。

 1日目夜のスピーカーズディナーは、やっぱり真剣に技術を追っている人たちが集まっているだけあって、楽しかった。まだまだ私は技術的にも精神的にも未熟な社畜4年生で、年上の方はもちろんのこと、最近だと高校生・大学生なのに、いまから自分がどれだけ努力しても追いつけそうにない人がインターネット上にはたくさんいるので、ちゃんと技術やお仕事に真摯に向き合う姿勢だけは忘れずに生きていきたいな、というなんか真面目な文章を、最後に書き残しておきます。

ひとまずみなさまお疲れ様でした。ありがとうございました。

appendix

iOSアプリ開発の全体像

超技術書展で頒布したiOSアプリ開発の全体像をだらだら書いた本を記事として公開。
ただのポエムです。

1. iOSアプリ開発を取り巻く環境

iOSアプリ開発には、基本的にmacOSを搭載したコンピューターとXcodeとよばれるソフトウェアが必要です。もともと主にObjective-Cという言語が使われるケースがほとんどでしたが、2014年6月にAppleがプログラミング言語Swiftを発表して以後の新規開発には、ほとんどの場合Swiftが採用されているようです。またSwiftは、Objective-Cのコードと共存できるため、もともとObjective-Cで開発されていたアプリを徐々にSwiftに移行しているという話もよく聞きます。

ただし、広告やSNSなどのSDKや、幅広く使われることが予想されていて安定性が必要なライブラリについては、依然としてAPIが安定しているObjective-Cで開発が行われているケースが多いと感じます。裏を返すとSwiftは言語としてまだ成熟していないということです。Swift2系までではマイナーバージョンアップデートでも、激しい破壊的変更が行われていました。Swift3系ではある程度落ち着きは見えますが、安定しているとは言い難い状況ではあります。それでもObjective-Cに比べて平易な構文、オプショナルやクロージャといったモダンな言語機能、そして静的型付けによる安全なプログラミングなど、得られる恩恵が大きいのは確かです。

1.1. iOS, Xcode, Swift, macOSのアップデート

Appleは定期的にiOSのメジャーバージョンアップデートをリリースしています。またSwiftのアップデートもさかんに行われています。これらに対応するためにはXcodeの更新が必要になるケースが多いです。Xcodeはファイルサイズが大きく、回線速度にもよりますがダウンロードに数十分、圧縮ファイルの解凍にまた数十分かかります。さらに、新しいXcodeを入れるには、新しいmacOSを入れなければならないことが多々あります。macOSの更新に1〜2時間かかることが珍しくありません。

実際のところ、こうした大きな更新があると最悪、半日ほど開発がストップしてしまいます。また、これらの作業は開発者やCIサーバーも含め全体のマシンでやる必要があり、考慮に入っていないと意外に手痛い時間のロストとなります。

これまでの動向では、Swift下位バージョンの切り捨ては早く、新しいバージョンに素早く追従しないと最新のXcodeではビルドができないなどの問題が発生する可能性があります。Swiftを利用すると決めた時点で、遅くとも2〜3ヶ月以内に最新のSwiftバージョンでビルドできる状態に持っていくような開発体制をとれるよう、あらかじめ開発工数のバッファをとることを強くおすすめします。

1.2. Xamarinという選択肢

iOSアプリ開発にはSwiftやObjective-C以外の言語を使うこともできます。その中でも代表的なものが、クロスプラットフォーム開発ツールのXamarinです。これによりC#やF#といった言語でのiOSアプリ開発が可能になります。これらは言語としては安定していて、C#はエンタープライズ方面での実績も十分にあります。またIDEとしてVisual StudioやXamarin Studioなどを利用することができます。ストーリーボードなどのUIコンポーネントを見た目通りに配置しながら画面を作るためのツールInterface Builder相当のことも、これらのIDEで実現可能です。

Xamarin社はMicrosoft社に買収され、現在個人での利用や特定の条件下において無料で開発環境を手にすることができるようになり、徐々に普及している段階の技術です。とはいえ、すでにフェンリル社が開発を行なったNHK紅白歌合戦のアプリなどで十分な実績があり、実用に耐えうるものといってよいでしょう。

Xamarin.iOSとXamarin.Forms

XamarinのなかでもXamarin.iOSとXamarin.Formsという2つのAPI群の選択肢があります。Xamarin.iOSはiOS SDKのAPIとほとんど1対1に対応しており、SwiftやObjective-Cと似たような感覚でアプリを構成することができます。一方、Xamarin.Formsは各プラットフォームのAPIを抽象化したものを使ってアプリを構成していくため、Xamarin.Formsに特化した知識をつける必要があります。その代わり、1つのコードから複数のプラットフォームをターゲットとしたアプリを作成することができ、開発効率の向上やマルチプラットフォーム間での実装のズレを防げるといったメリットがあります。

1.3. React Nativeという選択肢

Xamarin以外にもクロスプラットフォーム開発ツールとしてFacebookが推し進めるReact Nativeという技術があります。すでにInstagram, airbnb, Facebook Messengerなど大きなアプリですでに利用されています。各プラットフォームにおけるUIコンポーネントを抽象化したReactコンポーネントを組み合わせてアプリを構成するという思想を持っています。おおよそReact.jsと同じような形でアプリケーションを構成することができます。最近流行りのReact+Redux構成を取ることもできるため、JavaScriptに詳しい方はチャレンジしてみるのもありかもしれません。

1.4 iOSアプリ開発未経験者がとるべき選択肢

iOSアプリ開発においては、基本的にiOS SDKの基本的な振る舞いを理解することは必須であるため、経験者がひとりもいないチームでの開発はObjective-CかSwiftを採用するのが良いでしょう。当然ながら書籍や情報の量、サポートできる人材の量も一番多いです。iOSアプリ開発経験者がいるのであれば、どの方法を選んでも良いと思いますが、Xamarin.Formsを選んだ場合には、iOS SDKを直接触った場合とかなり勝手が異なるはずなので、十分な技術調査・検討を行ってから採用することを強くお勧めします。

2. iOSアプリ開発の流れ

iOSアプリはおおまかに「企画」「要件定義」「設計」「実装」という流れで開発を進めていくことが多いでしょう。最終的にはAppleによる審査を経てApp Storeでの公開が可能になります。この審査は他のプラットフォームに比べて厳しく、単純で機能が少ないアプリはAppleによりリジェクトされる可能性が高いです。例えばアプリ開発の練習として簡単な電卓などを作っても、App Store上には類似のアプリが無数にあるため、公開できない可能性があるということになります。

2.1. 企画

アプリを通してどのようなユーザーにどのような体験を与えたいのか、ターゲットユーザーと実現したいことを明確にする必要があります。似たようなアプリがある場合は、それらの調査を行い、どのように差別化を図りたいのかを検討すると良いでしょう。また「App Store審査ガイドライン」に違反する内容のアプリはたとえ出来上がっていてもApp Storeに出すことができない可能性が高いため、企画を始める段階からある程度を考慮することを強くお勧めします。特にアプリ内課金を導入する際にはAppleの審査はよりいっそう厳しくなるため、審査ガイドラインに沿った形に企画を着地させる必要があります。

2.2. 要件定義/デザイン

おおまかな企画が定まったら、アプリをどのように構成するのかを考えるフェーズに入ります。ユーザーにアプリの中をどのように回遊してもらい、どのような体験を提供するのかを具体化させていきます。また提供するコンテンツやアクションの階層構造/論理構造をはっきりとさせておくと、要件やデザインに落とし込むときに混乱を防ぐことができるので、この段階で整理しておくといいでしょう。例えば電子書籍リーダーを作る場合は、本一覧がベースの階層となり、1つ深い階層にシリーズが存在します。さらにシリーズには複数の本が紐づくといった具合です。

おおまかにやりたいことが見えてきたら、プロトタイプを作成してみましょう。紙ベースで画面を描いたり、矢印で動きを表現したりといった簡単なもので構いません。またAdobe Experience Design(XD)などを使うとより高度なプロトタイピングが行えます。実装コードを書かずにおおまかな動きを見ることができるため、複数のチームメンバ間でイメージを共有するにはうってつけのツールだといえます。iOSアプリの細かなデザインについての話は3章に記します。

2.3. 設計/実装

要件がある程度定まったら、アプリの技術的な設計フェーズに入ります。また特に要件のなかで実現が難しい点があれば、本当に実現可能なのか検証してみる必要があります。具体的な話は4章以降に記していきます。

2.4. ベータテストと品質保証

開発中はCrashlytics BetaやDeployGate、小規模であれば自前でのAd-Hoc配信などを通して開発チーム内でドッグフーディングを行うことにより、アプリの不具合検出や改善などを行います。また、ある程度の状態まで達したら開発に携わっていない第三者にも利用してもらい、フィードバックをもらえるようにしておくと、開発チームでは気づけない問題が発見できるでしょう。

いよいよリリースしても問題ないという段階が近づいてきたら、アプリの動作確認項目一覧表などを作り第三者にチェックをお願いすると、より安定したアプリをストアに出すことができると思います。これは一般的に品質保証(QA)のステップとよばれることが多いです。

2.5. 審査提出とリジェクト対応

大きなアプリとなると一発で審査をパスするのは難しく、Appleから何らかの指摘を受けてリジェクトされると思っておいたほうがよいでしょう。あらかじめリジェクトされることを想定して、ある程度アプリが出来上がってきたら、とりあえず審査に出してみるのも戦略のひとつです。これによりリジェクト対応のための仕様変更が生じる点を早めに知ることができます。

2.6. リリース

審査に通過したら晴れてアプリをApp Storeにリリースすることができます。審査提出時にはリリースタイミングのオプションがあり、そこで指定されたとおりにリリースが行われます。オプションは以下の通りです。

  • 手動でリリース: 審査通過後、リリースボタンを押したタイミングでリリースされる
  • 自動でリリース: 審査通過後、自動でリリースされる
  • 指定時刻以降に自動でリリース: 審査通過後、指定の時刻を過ぎたタイミングでリリースされる

なお、オプションはiTunes Connectというアプリの管理に使われているサービスの仕様変更によって変わる可能性があります。

3. iOSアプリのデザイン

iOSアプリのUI/UXに関してはAppleが公式に「iOSヒューマンインターフェースガイドライン」を制定しています。ガイドラインに沿わないデザインや実装を行うと一部は審査でリジェクトされる可能性があるため、開発を始める前にざっくりと目を通しておくとよいでしょう。ここではアプリ全体のデザインに影響してくるポイントを数点、記述します。

3.1. なるべく標準UIに沿ったデザインにする

特段デザインにこだわりがなければ、iOSのメールやSafari、設定画面などの標準的なアプリに沿った形でUIコンポーネントを利用し、画面を構成していくのがよいでしょう。UIコンポーネントを過剰にカスタムして使うと、場合によってはユーザーがどのように利用すればよいのか迷ってしまう可能性があります。また、iOSバージョン間で見た目や振る舞いを統一するのが難しくなり、最悪の場合は特定バージョンにおいて期待した動作を提供できなかったり、クラッシュを引き起こしたりする原因にもなります。

3.2 アプリ内の画面遷移

アプリを作る際に1画面だけで構成することは非常に稀で、ほとんどの場合には画面を遷移させる必要が出てくるでしょう。iOSの画面遷移には、主に次の2つのパターンが存在します。

  • プッシュ遷移
  • モーダル遷移

プッシュ遷移とはiOSの設定画面などで見られる右方向に階層構造を掘るように遷移するタイプのものを指します。この遷移は、スワイプで戻ることができ、コンテンツ階層間の移動をスムーズに行うのに適しています。この階層構造は、提供するコンテンツの階層構造と揃えてあげるのが一般的で、ユーザーにも理解しやすい形になるでしょう。たとえば音楽プレイヤーであるiTunesアプリは、ライブラリ→プレイリスト一覧→プレイリスト→楽曲というコンテンツ階層構造になっています。当たり前のことではありますが、きちんと分類して構成されているアプリは意外に多くありません。アプリデザインの構成を考える際に同時に提供するコンテンツ階層構造を整理することは、きっとデザインをする上でも役に立つことでしょう。

一方、モーダル遷移は、ビューが現れている間はその要素内でしか操作ができないようなものを指します。例えば、iOSのSafariのブックマーク一覧はこのタイプの遷移をします。また注意喚起のダイアログなどもモーダル遷移にあたります。何かオプションを指定したり選択したりする際に使われる傾向にあります。しかし、モーダルを閉じるには基本的にはタップをする必要があるため、ユーザーに煩わしさを感じさせてしまう可能性が高まります。最近は、モーダルビューを前の画面の上に浮いた状態で表示し、モーダル画面自体をスワイプすることで閉じる実装も目立つようになってきました。これにより閉じるためにタップをしなければならない問題が解消され、モーダル遷移に対するストレスを緩和させることができるため、可能であればそういった実装も考えてみると良いかもしれません。

3.3. デバイスの大型化とデザイン

iPhone 6 PLUSの登場時には、そのデバイスの大きさに随分と驚いた方も多いのではないでしょうか。実際iPhone 5のデバイスサイズは4インチであったのに対して、iPhone 7 PLUSでは5.5インチになっています。解像度も高くなり表示領域が増え、デザイン表現の幅が広がったのは間違いありません。

しかし、デバイスが大型化する一方で、人間の手の大きさは変わっていない点には注意する必要があります。右手でデバイスを操作する場合、左上や左下に配置したボタンなどには指が届きにくく、アプリのスムーズな操作の妨げになります。以前はモーダル画面の閉じるボタンを左上に配置するケースが目立っていたのですが、近年は右上や右下などに配置されているのをよく見ます。また、先述したとおり、モーダル画面自体を上下にスワイプすると閉じることができるように構成されているものもよく見ます。本質的には触り心地が良い形に画面を構成していければ、きっと良いアプリになるのではないかと考えています。

4. アプリをどのように構成すれば良いのか

初めてアプリ開発をする際に何に気をつければよいのか、とても不安になる気持ちは非常にわかります。筆者も初めてアプリを構成する際に何かアプリ開発特有の構成・設計を取る必要があるのではないかと思い調査をしました。結局のところネイティブアプリは、裏で処理をしつつも、ユーザーの入力を常に待ち受けつづける必要があるため、UIスレッドをブロックしないように注意するという点に注意していれば、一般的なプログラミングとほとんどかわらないと思います。したがって基本的なプログラミングができる方は何も心配せず、以前から実践していた技法を使いアプリを構成することができるでしょう。

iOSアプリ開発が本当に初めてである場合は、まずラベル(UILabel)、ボタン(UIButton)、テキストフィールド(UITextField)、画像(UIImage)などの基本的なコンポーネントの使い方を覚えると良いでしょう。続いて複雑なビューを構成する基本的な要素であるスタック(UIStackView)、テーブル(UITableView)、コレクション(UICollectionView)、スクロール(UIScrollView)、タブ(UITabBar)の使い方を学ぶと、自分の思い描いたビューを実現するための下地が整うのではないでしょうか。

4.1. 複雑な設計を採用する前に考えたいこと

近年、iOSアプリ開発をする上でどのような設計手法を取るかというような話題をよくみかけます。「iOSクリーンアーキテクチャ」や「ヘキサゴナルアーキテクチャ」など熱心に議論が行われています。これらの議論や記事ではアプリの規模感についての前提が共有されていなケースが多く、場合によっては過剰な構成となり、コードの可読性や開発のスピードを下げてしまうこともあるでしょう。開発メンバー間で考え方も一致させていく必要があり、本当に必要なものが何なのかを見極めることが非常に重要です。

iOSアプリのコードベースは往々にしてそれほど大規模なものにはならず、だいたい1万〜2万行程度で構成されることが多いと思います。アプリ全体のアーキテクチャパターンを考えることは確かに大切なことですが、私自身はSOLID原則やDRY原則、YAGNI原則などのシンプルで基本的なプログラミング原則を意識してコーディングしていくように心がけています。アーキテクチャのたくさんの決まりごとを意識しつづけるのは難しいことです。少数のシンプルで明確な決まりごとを意識していると実は自ずと、本に書かれているようなアーキテクチャになっていることは多々ありますし、そもそも複雑なアーキテクチャの根底思想にはシンプルな原理原則があることが多いと思います。

4.2. ライブラリの選定

アプリのすべてのコードを自前で書くことは稀で、多くの場合オープンソースライブラリの助けを借りることになると思います。ライブラリをうまく使いこなせば大幅に開発期間を短縮することができ、場合によっては多くの人に使われたり、メンテナンスされているため、一人で書いたものに比べ品質の高いコードを利用することができるなどというメリットもあるでしょう。

ただし、Swiftのライブラリについては、今後予想される言語自体のアップデートに継続的に対応させる必要があります。過去に大きな変更が幾度も入ったため、GitHubでStarがたくさんついていて、多くの開発者が利用しているライブラリでも、最新の言語バージョンにアップデート対応がされず、放置されていることは珍しくありません。利用する前に、メンテナンスが継続して行われているかをGitHubのPulseなどで確認しておくことをおすすめします。また、メンテナンスが止まってしまった場合、公開リポジトリからフォークして、自分でメンテナンスしていく覚悟が必要です。

これはSwiftのライブラリに限ったことではないですが、基本的にはコードの8割程度をざっくりと斜め読みし、コードの設計・品質・メンテナビリティ・適切なテストが存在するかなどを確認してから依存を決めると失敗がないと思います。また利用した各ライブラリのライセンスを遵守し、必要であれば必ずライセンス表記をしましょう。

4.3. ライブラリへの依存

ライブラリを導入すると一口に言ってもいろいろなやり方があります。たとえば秘匿情報などを管理できるキーチェーンにアクセスするライブラリを使うことを想定してみましょう。何も考えずにViewControllerの必要な箇所でライブラリをimportして依存コードをばらまいていくというやり方は、最初の実装者にとっては一番手が抜けて楽かもしれません。しかしこれには大きな問題があります。ものにもよるとは思いますが、おそらくライブラリを利用している周辺のコードは似たような実装が繰り返し登場しているのではないでしょうか?またライブラリのインターフェースが変更されたり、利用するライブラリを差し替えたりする場合、あちこちに散らばったコードに手を加える必要がでてきます。

したがって、個人的にはライブラリを利用する際にはなるべく依存コードを記述する範囲を狭くするように意識することが多いです。大半の場合はひとつのクラスの中に閉じ込めることができるはずで、その上でプロトコルを切り、実装クラスを差し替えられるような構造にするのが好みです。こうすることによってライブラリを差し替えたり、自前の実装に切り替えたりするなどの対応も容易になります。またテストの書きやすさにも繋がる場合もあると思います。

5. アプリと非同期処理

ユーザーインターフェースの存在するアプリは常にユーザーからの入力を受け付ける状態を保たなければならないという制約があります。したがって、何か重たい処理をするときは別のスレッドに仕事を任せる必要があります。この重い処理にはどんなものがあるでしょうか。例えばサーバーにデータを取得する際はリクエストを送ってからレスポンスが帰ってくるまで時間がかかります。この間ユーザーの入力を一切受け付けないアプリは控えめにいって最悪でしょう。また画像の変換や複雑な計算などはユーザーからのアプリへの入力をブロックしてしまいます。

これを避けるためには、重たい処理はユーザーからの入力を受け付ける担当とは別のものに任せればよいでしょう。ユーザーからの入力を受け付けている窓口はメインスレッドとよばれています。対してその裏で処理を行なっているものをバックグラウンドスレッドとよんでいます。また、あるタスクの実行を止めずに別の処理を行うことを非同期処理と言います。iOSアプリ開発において非同期処理はスレッドを利用して実現されていますが、Swift, Objective-Cからは開発者が直接スレッドを触ることなく非同期処理を取り扱える仕組みが用意されています。それがGrand Central Dispatch(GCD)とオペレーションキューになります。それぞれどのようなものかざっくりと特徴をみていきます。また、Appleが公式で提供している「並列プログラミングガイド」および「スレッドプログラミングガイド」を参照するとコードレベルの技術詳細に迫ることができると思いますので、ご覧ください。

5.1. Grand Central Dispatch(GCD)

GCDを利用する場合もオペレーションキューを使う場合も、基本的にはキューにジョブを積むというのが基本的な実装内容になると思います。ではこの2つの何が違うのかというと、用意されているキューの種類とジョブをクロージャで渡すのか、オブジェクトで渡すのかという点になります。

GCDには、キューイングされた処理を逐次実行していく直列ディスパッチキュー(Serial Dispatch Queue)と並列に実行していくのが並列ディスパッチキュー(Concurrent Dispatch Queue)が用意されています。さらに特別なキューとしてメインスレッドで行いたいタスクをキューイングするためのメインディスパッチキューというものが用意されています。メインスレッドはひとつしかなく、並列にできないので当たり前ではあるのですが、これは構造的には直列ディスパッチキューになります。

さて、実際のアプリの中でこれらがどのように利用されるかを少し想像してみましょう。例えばボタンを押したイベントを皮切りにサーバーにHTTP通信を走らせ、その結果をテキストボックスに表示するケースを考えてみましょう。最初にメインスレッドがボタンの押下イベントを受け付け、イベントハンドラを呼び出します。続いて、イベントハンドラは並列ディスパッチキューにクロージャをわたして、あとの処理をバックグラウンドスレッドにお任せします。このように、裏側で行わせたい仕事をキューに積んで放置することにより、ユーザーからの入力を受け付けられる体制に即座に戻ります。一方、バックグラウンドスレッドではどのようなことが行われているでしょうか。並列ディスパッチキューに渡されたクロージャの中身をみてみましょう。まずHTTPリクエストをサーバーに送るでしょう。そしてレスポンスが帰ってきたら、そのデータをよしなに加工して、テキストボックスに反映させる必要があります。このときに注意が必要で、基本的にUIコンポーネントを更新する際はメインスレッドでやる必要があります。したがって、加工し終わったデータの準備ができたら、今度はメインスレッドに処理を行わせるための直列ディスパッチキュー(DispatchQueue.main)にクロージャでお仕事を渡します。お仕事内容は単純にデータをテキストボックスに反映させるだけです。

5.2. オレペーションキュー

オペレーションキューを用いる非同期処理では、タスクを表現したデータ構造であるOperationを作り、キューに渡していくという流れになります。したがってあらかじめタスクを仕込んでおいて一気に並列/直列で実行するなどということが可能です。実際のところGCDのラッパーでしかないため動作原理はほぼほぼ同じになります。しかし、クロージャではなくタスクというオブジェクトを引き回せることでより柔軟で複雑なプログラミングが可能になると思います。

5.3. スレッドセーフな実装

複数のスレッド間で共有されるオブジェクトは不正な状態になる可能性をはらんでいます。不変なオブジェクトであれば問題はないですが、状態を持つオブジェクトには不正な状態になることを防ぐための実装を施してあげる必要があります。一般にマルチスレッド間でのオブジェクト共有に対して安全であることをスレッドセーフな実装とよんでいます。スレッドセーフな実装を実現させるためのツールにはアトミック操作とメモリバリア、ロック、条件変数などがあります。それぞれ特徴が異なっており、用途に適したものを利用する必要があります。詳細についてはAppleが公式で提供している「スレッドプログラミングガイド」を読むと良いと思います。

6. アプリ内通信のこれから

多くのアプリではウェブAPIを利用したり、画像/音声/動画リソースをインターネット上から取得します。これからSwift/Objective-Cで開発をはじめようという方はどのようにしてHTTPリクエストを走らせるのかという点が気になるのではないでしょうか。

ネットで検索をするとAFNetworkingやAlamofireといったライブラリの名前がヒットすると思います。しかし個人的には標準で提供されているURLSessionで十分足りると考えています。複雑なPOSTリクエストの組み立てなどには一部ライブラリの助けがあると楽をすることができるかもしれませんが、それを除けばライブラリに実装されている機能を利用する機会はそれほど多くないでしょう。通信ライブラリに限らない話ですが、本当にそのライブラリを導入する必要があるのか、よく検討してみてください。

6.1. App Transport Security

App Transport Security(ATS)とはiOS9.0以降で導入されたサーバークライアント間でのセキュアな通信を保証するための仕組みです。Appleが推奨するTLSバージョンと暗号スイート、サーバー証明書とそのハッシュアルゴリズム、サーバー証明書の署名キーを満たしていない場合に接続エラーとなります。

2017年4月現在ではATSに対応することは必須ではなく、HTTP通信やAppleの推奨条件を満たさないHTTPS通信を行いたい場合は、Info.plistに設定を追加することでATSによる接続エラーを回避することができます。しかしながら、AppleはATSに正当な理由なく対応していないアプリをリジェクトするとの予告を出しており、今後アプリ開発をしていく上ではこれに対応することはほぼ間違いなく必須条件となるでしょう。

少なくとも自前で立てているサーバーと通信を行う場合は、Appleが定めた推奨条件に対応させましょう。ただし自分の管理外サーバーとの通信を行う場合は、ATSに対応しない正当な理由として認められるようです。

6.2. APIクライアントは人間の書くものではない

大半のアプリではREST APIを叩き、そのレスポンスをもとにビューを更新するなどの処理が入るのではないでしょうか。こんなときにはAPIクライアントの実装が必要になるでしょう。

残念ながらSwiftでAPIクライアントを書く作業はSwiftyではありません。URLSessionを用いてレスポンスを取得し、正常なリソースが得られたらJSONなりXMLなりをパースしてJSONObjectを手に入れます。続いてJSONObjectの各キーから値を取り出してSwiftで定義したエンティティの構造体にマッピングします。JavaやC#などを使うとシリアライズやデシリアライズの工程はだいたい手で書く必要はなく、十分に実績のあるライブラリが自動的にやってくれるため、とてもSwiftyなのですが、Swiftには現在そのような機能を実現するライブラリは存在しないようにみえます。またあらかじめスキーマが決まっているエンティティの構造体を書くのも非常に面倒臭い作業で自動化したい機運が高まります。

APIクライアントのレイヤーを自動で解決するための方法はいくつかあります。ひとつ目はSwaggerというREST API作成のためのフレームワークを利用する手法です。仕様を表現したYAMLファイルから自動でAPIクライアントのコードを生成できるのが特徴です。

またREST APIからは外れますが、Protocol Buffersを使うことによりデシリアライズやエンティティの作成を自動化できます。こちらはサーバー側から送出されるレスポンスもProtocol Buffersに対応させなければならないため、自前のサーバーを利用したアプリ作成のときに使える手段となります。サーバーとクライアント間の通信も含めて、すべて自動でコード生成したい場合はRPCフレームワークのgRPCの利用を検討してみてください。

7. ユーザーに笑顔を届けるまでがiOS開発

Appleによる過酷なダンジョンを切り抜けついに審査を切り抜けたみなさんは、ついにリリースボタンを押すことになるでしょう。いままで開発をすすめてきたメンバーと一緒にリリースボタンを押すとウェイ感がでてとてもエモいので是非おためしください。

7.1. AppStoreのねぼすけ

さて、時間はお昼の12時、無事リリースボタンを押した我々はAppStoreに飛び、アプリをダウンロードしてみようと試みます。しかしながら、アプリは見当たりません。Appleの実装はとてもlazy(怠惰)なのでリリースボタンを押してから反映までに30〜60分程度要すると思っていただいてよいでしょう。もし決まった時間にプレスリリースやSNSなどでリリース告知をする際には、あらかじめこっそりとアプリをリリースして、AppStoreに反映させておくのが良いと思います。

そんなこんなでアプリは13時にはストアに反映されていたとしましょう。ところがtwitterでエゴサするとダウンロードがうまくできないとの酷評が。リリースと同時につけられる1ツ星評価。実際のところ何が原因か分かっていないのですが、お昼の時間帯などはAppStoreからのダウンロードがうまくいかないときがあるようで、個人的にはリリースはアプリのユーザーがアクティブでなくなってくる時間帯にするようにしています。個人的にはAppStoreのアプリ配信サーバーを増強してほしいという気持ちをここに掲載させていただきます。

7.2. 俺たちの闘いはこれからだ!

アプリをリリースして、開発を終わらせるぞ!そう思っていた時期が私にもありました。しかしアプリ開発はリリースしてからが本番です。まずは多くのユーザーに使ってもらうためにきっと様々な仕掛けが必要でしょう。また発生させてしまった不具合の対応や、アプリをさらに快適に利用できるような新機能の提供などやることはたくさんあるはずです。そう、俺たちの闘いはこれからだ!

System.Net.Httpのリクエストやレスポンスをロギングする

SwiftのURLSession使って自前でHttpClient書いてたときは、リクエストパラメタとかいろいろをデバッグ時にログ出力してくれる便利なやつを自作していたんですが、.NETのHttpClientまあそのまま使うので、ロギングどうしようと思ってたらちゃんと用意してくれている。とても良い。

これを使ってリクエストを送ると例えば以下のようなログ出力が得られる

便利

ES2015+Flowなlambda関数をApexで管理する

ES2015 + 型チェッカー flow で書かれた AWS Lambda 関数を Apex で管理する方法について、つらつらとメモ。この記事は @nagisio 先生のご指導のおかげで成立しています(謝辞)。

  • キーワード
    • AWS Lambda
    • yarn
    • ES2015
    • flow
    • Apex

記事読むの面倒くさいので、動くリポジトリよこせという方はここをcloneすべし(動かしてから理解する方が楽なのですよねー :wakaru:)

ES2015 + flow + Apex の環境構築

yarn の導入

導入はかんたん。

  1. npm initpackage.json を作る
  2. npm install yarn --dev で yarn を導入する
    • global に入れたい方はどうぞ

package.json はきっとこんな感じになっているのではなかろうか

ESS2015 + flow の環境構築

まずは必要なものを片っ端からいれていく

次に .babelrc を次のようにする

node_modules/flow-bin/cli.js init でflow の設定ファイル .flowconfig を作り、以下のような感じにする

もう多分この時点で ES2015 + flow のコードが書けるので適当に src/hello/index.js に適当なコードを書いてみよう

続いてトランスパイルして functions 下に成果物を出力してみよう

成果物は次のようになっているだろう

良い感じにハローワークに行きたいくなる良いラムダ関数ですね。さて、ここまできたらあとは Apex を導入して AWS にデプロイするだけです。

ちょっとその前に、トランスパイルするコマンドが長ったらしくてだるいのでエイリアスを張っておきましょう。package.json の script の部分をちょちょいといじるといい感じに npm run build で諸々実行できます。

Apex の導入

今回 AWS Lambda 関数の管理には Apex をつかいます。Apexの挙動は非常に単純で project.json に指定されたリソースやタイムアウト時間、IAMロールの設定で、functions直下にある各ディレクトリをそれぞれラムダ関数とみなし、デプロイしてくれます。

導入はかんたん

project.json をイカのよう設定すればよいでゲソ(各自IAMロールは適切なものを指定してください)

apex deploy でデプロイできます。apex invoke hello で実行できます。

良い

ESLint の導入(お好みで)

ESLintを入れたい方は適当に必要そうなやつをどうぞ(適当)

.eslint を適当に書く

deploy 前に uglify の処理を入れる

lambda の起動時間は多分デプロイされる成果物のサイズが小さい方がはやいので、uglifyをかけたほうがよさそう。packaage.jsonを書き換えればいい感じに実現可。

npm run build:prod で functions 下にできる成果物を確認してみるとちゃんとできてるか確認出来る。

ステージ管理

このあたりの対応が一番筋がよさそう👉 Lambda with Apex: 環境変数で環境別にLambda環境を整える

おわりに

ES2015 + flow + Apex で快適な AWS Lambda ライフを!