Upgrade to Pro — share decks privately, control downloads, hide ads and more …

カーナベル株式会社2024年2月 エンジニアイベント資料

andoshin11
February 10, 2024

カーナベル株式会社2024年2月 エンジニアイベント資料

カーナベル本社で行ったWeb Components Hands-onイベントの当日資料です

andoshin11

February 10, 2024
Tweet

More Decks by andoshin11

Other Decks in Technology

Transcript

  1. 本日は遠方よりご参加ありがとうございます! 本日のアジェンダ • 前半の部 ◦ イントロ ◦ カーナベルを支える技術について (〜11:15) ◦

    Web Components(Lit)を利用したモダンなUI開発体験 (~12:30) • 休憩 (~13:30) • 後半の部 ◦ Deck Makerのブログ埋め込み機能を作ろう (~15:30)
  2. 自己紹介 • 安藤真 (@andoshin11) • 役職:テックリード • 入社:2021年4月 ◦ ex:

    LINE, メルカリ, Folio, 朝日新聞社, etc… • 趣味:遊戯王(マスターデュエル), FPS, グルメ, ウィスキー • 好きな技術:TS, Vue.js, Nuxt.js, k8s, Terraform, GO
  3. 01 02 モダンな技術を利用したプロダクト開発の楽しさを知ってもらう 本日のゴール 「トレカ × Tech」に挑戦する弊社について知ってもらう - 世間的にみても結構進んだ取り組みをしていると思う -

    あわよくば友人やネットでみなさんに宣伝して欲しい - Web Components(Lit) + TypeScript + Storybook - みなさんが実務でも利用できる部分があると嬉しいです
  4. Deck Maker コアとなる技術 1. 快適に利用できるSingle Page Application ◦ 直感的にデッキ編集が行える UI設計

    ◦ 高速に仮説検証が行える改善基盤 2. 業界一のカード検索・デッキ検索機能 (自社調べ) ◦ 数百万デッキに対して 2~300msで複合検索可能な検索バックエンド ◦ ECサイトならではの価格データ連携
  5. Deck Maker コアとなる技術 1. 快適に利用できるSingle Page Application ◦ 直感的にデッキ編集が行える UI設計

    ◦ 高速に仮説検証が行える改善基盤 2. 業界一のカード検索・デッキ検索機能 (自社調べ) ◦ 数百万デッキに対して 2~300msで複合検索可能な検索バックエンド ◦ ECサイトならではの価格データ連携
  6. What’s good? • Vue.js向けのフルスタックフレームワーク ◦ Dynamic Routing, Server API, Build

    Optimization, Middleware, etc… ◦ 充実したModule ecosystem ▪ 弊社ではSentry, Google Analytics等のModuleを利用 ◦ Webアプリケーション開発に必要なことを「大体なんでも」やってくれる ◦ Pluginをうまく活用すればDIもサクッとできてテスタビリティが高い
  7. Deck Maker コアとなる技術 1. 快適に利用できるSingle Page Application ◦ 直感的にデッキ編集が行える UI設計

    ◦ 高速に仮説検証が行える改善基盤 2. 業界一のカード検索・デッキ検索機能 (自社調べ) ◦ 数百万デッキに対して 2~300msで複合検索可能な検索バックエンド ◦ ECサイトならではの価格データ連携
  8. What’s good? • ドキュメント格納型の検索エンジン。とにかく速い & 高機能 • RESTFul APIによりクライアント(Browser)から複雑なクエリを組み立てて検索を実行 できるためデッキメーカーと相性が良い

    • 実際のクエリ利用例 ◦ レベル7魔法使い族効果モンスターで破壊以外の除去効果を持つカード ◦ フェアリー・ライフとフェアリー・ Re:ライフを含む水・自然文明のみかつ 5,000円以 下のデッキ ◦ 等々
  9. Deck Maker (Nuxt.js) Firestore Firebase Functions カーナベルECサイト Elasticsearch 1. カード・デッキ検索

    2. デッキを保存 3. 関数をトリガー 4. 価格データを取得 5. 正規化したデッキ データをWrite ※ 実際のアーキテクチャとは異なります
  10. ECサイトリニューアル(WIP) • 現行EC老朽化と事業拡大に対応するべく式年遷宮中 • Microservices分割(とはいえ細かく分けすぎないように ) ◦ 販売サイト ◦ 買取サイト

    ◦ トレカデータサービス ◦ お客様情報管理サービス ◦ 社員管理サービス ◦ 認証基盤 ◦ etc… • 「難しいことを難しくやらない」という姿勢で適切に先端技術を取り込んでいく
  11. Browser Frontend (Next.js) Contour (Envoy) Auth Gateway Argo CD・ Workflows

    Cilium OTel Collector Microservice A Microservice B Microservice C
  12. Kubernetes • Kubernetes自体は4年ほど前から利用中。 GKE(画像AI学習基盤) & EKS(新EC) • Middlewareをサクッと導入しやすいのが便利 ◦ Helm

    chart repositoryを用意してMiddleware versionsをgit管理 • 何かあった時にソースコードレベルで原因調査を行える安心感 ≠ ブラックボックス • Terraform Moduleを適切に設計すれば multi-cluster構成も導入しやすい ◦ Middlewareの破壊的変更などを検証する際は clusterごと壊したり作り直したくなる ことが結構ある ◦ multi-clusterであればcluster-levelの変更をユーザー影響なく検証できる ◦ 現在はmain-cluster, experimental-clusterのdual構成で常時稼働中。一方に変 更を加えて動作確認が完了した段階で ALBの向き先を切り替える運用 ◦ 徹底的にstatelessなclusterになるように意識している
  13. Knative • Cloud Runのようなzero-scalingやeventingをEKSでも行いたくて導入 • EKSはNodeの稼働時間に応じて課金されるため、業務時間外の Staging Cluster費用が 勿体無い →

    Knativeならリクエストを送るまで Pod数を0にできて経済的 • まだまだ導入企業は少ないものの、小さい開発組織とは相性が良さそう • 余談: カーナベルは日本の会社として唯一 Knative Adoptersにリスティングされてる
  14. Cilium • eBPFで動作するネットワーク制御ツール • Observability ◦ カーネルレベルでCluster内の通信を追えるため、ネットワーク流量や経路の監視が 行いやすい ◦ HubbleというIstioでいうKiali的なService

    Map可視化ツールもある • Security ◦ Namespace単位でNetwork Policyを定義でき、Cluster外へのアクセスを制御で きる ◦ アクセス可能な外部サービス (決済プロバイダー, Firebase, Aurora, etc…)をホワ イトリストで定義し、万が一サーバーに侵入されても攻撃者のサーバーへデータを持 ち逃げされないよう制御
  15. Q&A

  16. そもそもWeb Componentsって何? • 再利用可能なコンポーネントを独自の HTML Tags(Custom Elements)として定義するWebの標 準仕様 • 2011年頃に初めて提唱され、Google主導のPolymer

    Projectなどを経て2016年頃から順次ブラ ウザ実装が進む。2020年以降は全てのモダンブラウザで利用可能 • React / Vue / Angular / Svelteといったフレームワークに依存しない = ブラウザネイティブのラン タイムで動作。ポータビリティの高いコンポーネント 定義が可能に • 実際は... ◦ Web標準として汎用性重視の仕様となったため重厚な書き味に ... ◦ LitやSvelte等で定義したコードをcompileして利用するケースが大半
  17. Web Componentsを構成する要素 • Custom Elements ◦ 開発者が独自のHTML Tagsを定義し、挙動をカスタマイズできる • Shadow

    DOM ◦ Document APIやCSSの適用対象を特定のスコープ (Shadow DOM)に限定することが可 能になる。各コンポーネントの CSS定義が他の定義と干渉しない! • HTML Template ◦ <template/> <slot/> というフラグメント要素(ページ読み込み時に描画されない DOM要素)の活用 • ES Modules
  18. CodeSandbox Link 1. HTMLElementを拡張してカ スタムクラスを定義 2. shadowRootにHTMLを描 画。getAttributeで親要素から 渡された値を参照 3.

    customElements.defineで カスタムタグを定義 4. 定義したカスタムタグを呼び 出し。Attributeで任意の値を指 定
  19. Timer Componentを作ろう ① • src/timer.ts を作成 • index.htmlの<body/>内を全て削 除しtimer.tsを読み込み •

    <timer-component/>を呼び出し • この時点ではまだ画面に何も表示さ れない
  20. Timer Componentを作ろう ② • HTMLElementを拡張して TimerComponentを定義 • Shadow DOMやattribute監視の設定を 諸々追加

    • connectedCallbackに初期化処理を記 述 • customElements.defineを呼んで <timer-tomponent/>というカスタムタ グを定義
  21. Timer Componentを作ろう ③ • timer private propertyを定義 • startTimer() ◦

    setIntervalで1000ms = 1sご とにHTMLを書き換える ◦ タイマーが終了したら timer-finishedイベントを発火 • stopTimer() ◦ タイマーを初期化する
  22. Timer Componentを作ろう ④ • Event Listenerの設定 • connectedCallback() ◦ 読み込み時の初期化処理

    • disconnectedCallback() ◦ オフロード時のリセット処理 ◦ メモリリークの防止 • アロー関数におけるthisのスコープに注 意
  23. 正直、仕事で使うには辛い・・・ • 現代のUIコンポーネント開発に必須な機能 ◦ Reactに代表される宣言的テンプレート定義 ◦ Vueに代表されるリアクティブなデータバインディング • どちらも自前で実装する必要がある 🔥

    • 手続き的なDOM管理 ◦ element.innerHTMLで一括更新を行うためパフォーマンスも悪い • リアクティビティの担保とデータバインディング ◦ class propertyにtemplateが依存した状態でpropertyが更新された場合、明示的に DOM の更新や参照部分の再計算を行う必要がある → 依存ツリーやbatch update queueの自 前管理が必要
  24. Lit: Simple. Fast. Web Components. • Googleの開発者主導のプロジェクト。 Polymer Projectの後継 •

    Web Componentsをより宣言的かつ生産的に開発するためのフレームワーク • コンパイル後はネイティブの Web Componentsに変換されるため再利用性が高い • Decorator(ref: TC39)を利用してreactive propertyを定義し、更新時にはbatch処理により影響 部分のみをatomicに更新してくれる = ハイパフォーマンス • その他の便利な機能 ◦ html関数や css関数とtagged template literalを組み合わせて安全なtemplateを記述 可能 = sanitize & virtual-node-treeの構築 ◦ Pre-definedなdirectiveを活用して記述量を削減できる ◦ TypeScript support
  25. LitでTimer Componentを作ろう ① • src/lit-timer.ts を作成 • index.htmlの<body/>内を全て削 除しlit-timer.tsを読み込み •

    <lit-timer-component/>を呼び 出し • この時点ではまだ画面に何も表示さ れない
  26. LitでTimer Componentを作ろう ② • LitElementを拡張する • @customElement decoratorでラップ • 親から受け取るdurationに@property

    decoratorを付与 • render() ◦ reactive propertyの変更に応じ て自動で実行される描画処理 ◦ html関数にtagged template literalを渡して宣言的に定義
  27. LitでTimer Componentを作ろう ③ • timer private propertyを定義 • startTimer() ◦

    setIntervalでduration propertyを更新。HTMLの書き換え は行わない ◦ タイマーが終了したら timer-finishedイベントを発火 • stopTimer() ◦ タイマーを初期化する
  28. LitでTimer Componentを作ろう ④ • Event Listenerの設定 • @click ◦ onClickの糖衣構文

    ◦ template内で直接 addEventListener相当の処理を定義 可能 = 宣言的定義 ◦ removeEventListenerも不要
  29. お題①: DMDeckInfo • デッキの基本情報を表示するコンポーネントを作る (完成系) • デザインは雰囲気で。paddingや細かいfont-sizeは特に指定しません • property: ◦

    deckData ← APIから取得するデッキデータ。今回は mock値で代用 • 表示する情報: ◦ サムネイル ◦ レギュレーション ◦ 更新日 ◦ デッキ名 ◦ ユーザー名 ◦ 閲覧数 レギュレーションの表示ルール • none → 殿堂ゼロ • advance → アドバンス • 2block → 2ブロック • party → デュエパーティー • Original → オリジナル
  30. お題②: DMTabs • デッキの表示領域を切り替えるコンポーネントを作る (完成系) • property: ◦ deckData ←

    APIから取得するデッキデータ。今回は mock値で代用 ◦ currentTab ← 現在表示中のタブ • dispatchEvent: ◦ change ← タブが選択されたら発火 ▪ new CustomEvent(‘change’, { detail: targetTab }) • その他仕様: ◦ currentTabはactive classを付与 ◦ メイン/GR/超次元はラベルの横に枚数を表示する ◦ deckData.dorumagedonがtrueの時のみドルマゲドンのタブを表示する ◦ deckData.zeronがtrueの時のみ零龍のタブを表示する
  31. お題③: DMDeck • 実際にサイトから呼び出されるデッキ取得 & 表示コンポーネント(完成系) • property: ◦ dmDeckId

    ← デュエマデッキID • state: ◦ currentTab ← 現在表示中のタブ ◦ 参考: Lit - Internal reactive state • methods ◦ changeTab ← DMTabsコンポーネントのchange eventをトリガーに実行。受け取った値 でstateを更新する • おまけ ◦ Storybook上でdmDeckIdを変更た際にデッキの再取得 & 再描画を行うには? ◦ 参考: Lit - Reactive update cycle
  32. oEmbedのフロー 1. 埋め込みURLへアクセス 2. embed endpointをheadで伝達 3. embed endpointへアクセス 4.

    Rich TypeのJSONを返却 5. JSONに指定されたiframeを描画 6. iframe srcで指定されたHTMLを返却