Slide 1

Slide 1 text

Remix + Cloudflare Pages + D1 でポケモン SV のレンタ ルチームを検索できるアプリを作ってみた 1

Slide 2

Slide 2 text

自己紹介 もやし丸 Software Engineer / Scrum Master GitHub: @kuroppe1819 Twitter: @kuroppe1819 2

Slide 3

Slide 3 text

作ったもの ポケモン SV のレンタルチームを検 索できるサイト https://pokemon-rental-teams- search.pages.dev/ 3

Slide 4

Slide 4 text

レンタルチームとは? インターネット上で公開されている ID を入力して、簡単にバトルチームを借りることが できる機能です。自分の育てたバトルチームを公開して、世界中のポケモントレーナー に使ってもらうことも可能です。 「バトルスタジアム」で世界中のポケモントレーナーとバトルしよう! 4

Slide 5

Slide 5 text

バトルチームの作り方 5

Slide 6

Slide 6 text

ポケモンを育てよう! 6

Slide 7

Slide 7 text

ポケモン SV 時代の育成 は「金」と「レイド」が すべて 孵化作業は過去の話 ステータスを上げるアイテムはす べて金で購入できる レイドポケモンを倒すとレベル上 げやテラスタイプを変更するアイ テムをドロップする 7

Slide 8

Slide 8 text

効率よくお金を稼ぐ 金策ニンフィアを育成し、学校最 強大会を A ボタン連打で周回する 大体 10 分で 10 万円稼げる 私は Arduino で自動周回できるよ うにしました 8

Slide 9

Slide 9 text

世代が進むにつれて育成のハードルが下がっている 9

Slide 10

Slide 10 text

というわけで皆さんも Let's ポケモンバトル 10

Slide 11

Slide 11 text

レンタルチームを借りてみよう! Q. レンタルチームはどこで公開されている? A. Twitter、Youtube、まとめサイト...etc 11

Slide 12

Slide 12 text

Twitter でレンタルチー ムを検索してみよう! # レンタルチーム , # レンタルパーティ or #pokemon vgc で検索! 12

Slide 13

Slide 13 text

Twitter でレンタルチー ムを検索してみよう! # レンタルチーム , # レンタルパーティ or #pokemon vgc で検索! → 自分のお気に入りのポケモ ンが含まれているチームを見 つけるのが大変 13

Slide 14

Slide 14 text

そこで役に立つのが Pokemon Rental Teams Search 14

Slide 15

Slide 15 text

Pokemon Rental Teams Search なら検索したポケモンが 含まれるレンタルチームを表示してくれます 15

Slide 16

Slide 16 text

ここから技術の話 16

Slide 17

Slide 17 text

Web アプリの構成 17

Slide 18

Slide 18 text

Web アプリの構成 18

Slide 19

Slide 19 text

pokemon-rental-teams-search-app Remix + Cloudflare Pages + Cloudflare D1 19

Slide 20

Slide 20 text

pokemon-rental-teams-search-app 20

Slide 21

Slide 21 text

pokemon-rental-teams-search-app の役割 レンタルチームの表示 検索 21

Slide 22

Slide 22 text

なぜ Cloudflare D1 を採用したのか Edge location で DB が動く = Origin server (DB)へのアクセス時間を短縮できる コールドスタートなし 22

Slide 23

Slide 23 text

なぜ Remix を採用したのか Edge location でのレンダリング - Remix and NextGen “Edge” Cloudflare Workers との連携が強力 23

Slide 24

Slide 24 text

Remix + Cloudflare D1 で検索アプリを作ってみる 24

Slide 25

Slide 25 text

プロジェクト作成 1. npx create-remix@latest 2. Cloudflare Pages を選択してプロジェクト作成 25

Slide 26

Slide 26 text

D1 データベース作成 ~ Worker と D1 をバインド D1 Get started - Cloudflare Docs を参照 26

Slide 27

Slide 27 text

データベースからデータ を取得してみる loader GET アクセス時のデータフェッチ を定義 loader の戻り値をコンポーネント 側の useLoaderData で受け取れる 27

Slide 28

Slide 28 text

検索を実装してみる - Component Remix の Form コンポーネントを使って 実装する例 28

Slide 29

Slide 29 text

検索を実装してみる - loader request からクエリ文字列を取り出す 29

Slide 30

Slide 30 text

ローカル開発環境で動作確認 Worker 起動オプションに --d1 , --persist を付与する wrangler pages dev ./public --d1= --persist $ npm run dev 30

Slide 31

Slide 31 text

完成 31

Slide 32

Slide 32 text

ポケモンレンタルチーム検索サイトの読み込み時間 250ms~350ms で応答できる(TTFB) レイアウトが変化した箇所だけフェッチするため、検索のレスポンスが高速 32

Slide 33

Slide 33 text

投稿, 更新, 削除の実装 action POST, PUT, PATCH, DELETE など のミューテーションを定義する form 要素, useSubmit などからリ クエストする ルートに対して GET 以外のリクエ ストが行われた場合、loader の前 に action が呼び出される。 33

Slide 34

Slide 34 text

Styling Flowbite を採用した - Tailwind CSS ベースの UI コンポーネントライブラリ バンドルサイズが 1MB を超えないようにライブラリを選んだ UI ライブラリや CSS in JS ライブラリを入れると 1MB に抑えるのがきつい 34

Slide 35

Slide 35 text

Remix v1.11.0 で CSS Modules と Vanilla Extract がサポ ートされました With this release, we can now support: Direct CSS side-effect imports CSS Modules Vanilla Extract remix v1.11.0 - GitHub 35

Slide 36

Slide 36 text

Astro を採用してもよか った コンポーネント側にロジックがな く、データを表示するだけ getRuntime を使うと .astro フ ァイルから Cloudflare runtime に アクセスできる Cloudflare Workers との連携は Remix の方が強力 36

Slide 37

Slide 37 text

pokemon-rental-teams-app まとめ Remix + Cloudflare D1 構成は  Edge location で DB 操作とレンダリングを行うので非 常に高速 Remix が変更があったレイアウトのみデータフェッチしてくれるため、検索のレスポン スも高速 バンドルサイズ 1MB (無料枠)の制限に注意 37

Slide 38

Slide 38 text

pokemon-rental-teams-search-data-sync Cloudflare Workers + Cloudflare D1 + AWS Lambda 38

Slide 39

Slide 39 text

pokemon-rental-teams-search-data-sync 39

Slide 40

Slide 40 text

pokemon-rental-teams-search-data-sync の役割 Twitter からレンタルチーム画像付きのツイートのみを取得して DB に保存する 40

Slide 41

Slide 41 text

Cron Trigger で Worker を定期実行 Worker の 「Triggers」 タブから設 定する 41

Slide 42

Slide 42 text

Cloudflare Workers の制限 V8 の JavaScript エンジンを使っているため、Node.js が動かない Worker limits - Cloudflare 42

Slide 43

Slide 43 text

Cloudflare Workers か ら Lambda を実行 AWS Lambda を叩くとレンタルチ ームの画像を含むツイート情報を 返してくれるので、そのレスポン スを DB に書き込む CPU runtime が 10ms しかないか つ、Worker 非対応のライブラリが まだまだ多いため、DB 操作以外の 処理は AWS Lambda に切り出した 43

Slide 44

Slide 44 text

レンタルチームの画像を 含むツイートを返す Twitter の Recent Search API を叩 いて取得したツイート情報から画 像の URL を取得する 取得した画像の URL を 画像比較 用の AWS Lambda に渡すと、画像 の一致率が返ってくる 一致率が閾値以上ならメモリにス タック、閾値未満なら破棄 44

Slide 45

Slide 45 text

画像の一致率を求める 単純な画素の比較 ユーザーは Switch の Twitter 連携 機能を使ってレンタルチームの画 像を投稿するので、縦横幅のサイ ズが 1280 x 720 の JPEG 画像に 統一されている JPEG 形式の画像をバイナリデータ に変換して比較しているだけ 45

Slide 46

Slide 46 text

AWS Lambda の並列実行 1280 x 720 の画像の画素比較にかかる時間は 1 枚あたり約 1 秒 100 枚ほどの画像を比較すると、Amazon API Gateway の Timeout 時間 30 秒を超えて しまうため、Promise.All で並列実行する 1 分 30 秒 →19 秒に短縮 Lambda URL を使うと Timeout を 15 分まで伸ばすことが可能だが、今回は素直に並列 実行した 46

Slide 47

Slide 47 text

これから ヒストグラム比較で類似度を算出するとスマホのカメラで直撮りしたレンタルチームの 画像も拾えるようになるかもしれない テンプレートマッチング法などで画像のポケモン名を抽出したい 総ポケモン数 x 対応言語数 x 手持ちポケモンの数 = 最大比較数 400 x 6 x 6 = 14400 47

Slide 48

Slide 48 text

pokemon-rental-teams-data-sync のまとめ 定期実行でレンタルチームのツイートを DB に書き込んでいる Cloudflare Workers は DB の操作のみ行い、他の処理は外部に切り出している レンタルチームの比較は単純な画素比較 画像比較の方法を変えると自動で収集できるツイートが増えるかも 48

Slide 49

Slide 49 text

全体のまとめ Twitter で公開されているレンタルチームを検索するアプリを作ってみたので、ポケモン 対戦に興味のある方はぜひ使ってみてください Remix + Cloudflare D1 で Edge location で動くアプリを簡単に作れるよ Worker の制限内に収まるように外部サービスをうまく活用してアプリケーションを設計 しよう 49