Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
カーナベル株式会社2024年2月 エンジニアイベント資料
Search
andoshin11
February 10, 2024
Technology
0
120
カーナベル株式会社2024年2月 エンジニアイベント資料
カーナベル本社で行ったWeb Components Hands-onイベントの当日資料です
andoshin11
February 10, 2024
Tweet
Share
More Decks by andoshin11
See All by andoshin11
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」Microservices認証認可基盤
andoshin11
0
290
Private Cloudを支える最高のユーザーガイド運用技術
andoshin11
0
270
TS CompilerがVueを喋れても良いじゃないか
andoshin11
0
690
ain't giving up type-safe Express
andoshin11
2
400
Type Safe "Everything"
andoshin11
0
220
Hack your Nuxt router!
andoshin11
0
1.2k
GatewayパターンとSchema駆動開発
andoshin11
8
1.3k
Catch up Nuxt.js 2019.02
andoshin11
0
1.9k
The future of Nuxt.js with TypeScript
andoshin11
0
80
Other Decks in Technology
See All in Technology
Autify Company Deck
autifyhq
1
39k
WINTICKETアプリで実現した高可用性と高速リリースを支えるエコシステム / winticket-eco-system
cyberagentdevelopers
PRO
1
190
使えそうで使われないCloudHSM
maikamibayashi
0
170
スプリントゴールにチームの状態も設定する背景とその効果 / Team state in sprint goals why and impact
kakehashi
2
100
なんで、私がAWS Heroに!? 〜社外の広い世界に一歩踏み出そう〜
minorun365
PRO
6
1.1k
Product Engineer Night #6プロダクトエンジニアを育む仕組み・施策
hacomono
PRO
1
470
Commitment vs Harrisonism - Keynote for Scrum Niseko 2024
miholovesq
6
1.1k
Shift-from-React-to-Vue
calm1205
3
1.3k
AIを駆使したゲーム開発戦略: 新設AI組織の取り組み / sge-ai-strategy
cyberagentdevelopers
PRO
1
130
Apple/Google/Amazonの決済システムの違いを踏まえた定期購読課金システムの構築 / abema-billing-system
cyberagentdevelopers
PRO
1
220
CyberAgent 生成AI Deep Dive with Amazon Web Services / genai-aws
cyberagentdevelopers
PRO
1
480
サイバーエージェントにおける生成AIのリスキリング施策の取り組み / cyber-ai-reskilling
cyberagentdevelopers
PRO
2
200
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
25
1.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
GitHub's CSS Performance
jonrohan
1030
460k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
A Philosophy of Restraint
colly
203
16k
Six Lessons from altMBA
skipperchong
26
3.5k
Music & Morning Musume
bryan
46
6.1k
Speed Design
sergeychernyshev
24
570
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
37
1.8k
Git: the NoSQL Database
bkeepers
PRO
425
64k
Transcript
2024年2月 エンジニア イベント資料 カーナベル株式会社
本日は遠方よりご参加ありがとうございます! 本日のアジェンダ • 前半の部 ◦ イントロ ◦ カーナベルを支える技術について (〜11:15) ◦
Web Components(Lit)を利用したモダンなUI開発体験 (~12:30) • 休憩 (~13:30) • 後半の部 ◦ Deck Makerのブログ埋め込み機能を作ろう (~15:30)
自己紹介 • 安藤真 (@andoshin11) • 役職:テックリード • 入社:2021年4月 ◦ ex:
LINE, メルカリ, Folio, 朝日新聞社, etc… • 趣味:遊戯王(マスターデュエル), FPS, グルメ, ウィスキー • 好きな技術:TS, Vue.js, Nuxt.js, k8s, Terraform, GO
01 02 モダンな技術を利用したプロダクト開発の楽しさを知ってもらう 本日のゴール 「トレカ × Tech」に挑戦する弊社について知ってもらう - 世間的にみても結構進んだ取り組みをしていると思う -
あわよくば友人やネットでみなさんに宣伝して欲しい - Web Components(Lit) + TypeScript + Storybook - みなさんが実務でも利用できる部分があると嬉しいです
カーナベルを 支える技術
Deck Maker
Deck Maker コアとなる技術 1. 快適に利用できるSingle Page Application ◦ 直感的にデッキ編集が行える UI設計
◦ 高速に仮説検証が行える改善基盤 2. 業界一のカード検索・デッキ検索機能 (自社調べ) ◦ 数百万デッキに対して 2~300msで複合検索可能な検索バックエンド ◦ ECサイトならではの価格データ連携
Deck Maker コアとなる技術 1. 快適に利用できるSingle Page Application ◦ 直感的にデッキ編集が行える UI設計
◦ 高速に仮説検証が行える改善基盤 2. 業界一のカード検索・デッキ検索機能 (自社調べ) ◦ 数百万デッキに対して 2~300msで複合検索可能な検索バックエンド ◦ ECサイトならではの価格データ連携
None
What’s good? • Vue.js向けのフルスタックフレームワーク ◦ Dynamic Routing, Server API, Build
Optimization, Middleware, etc… ◦ 充実したModule ecosystem ▪ 弊社ではSentry, Google Analytics等のModuleを利用 ◦ Webアプリケーション開発に必要なことを「大体なんでも」やってくれる ◦ Pluginをうまく活用すればDIもサクッとできてテスタビリティが高い
Deck Maker コアとなる技術 1. 快適に利用できるSingle Page Application ◦ 直感的にデッキ編集が行える UI設計
◦ 高速に仮説検証が行える改善基盤 2. 業界一のカード検索・デッキ検索機能 (自社調べ) ◦ 数百万デッキに対して 2~300msで複合検索可能な検索バックエンド ◦ ECサイトならではの価格データ連携
None
What’s good? • ドキュメント格納型の検索エンジン。とにかく速い & 高機能 • RESTFul APIによりクライアント(Browser)から複雑なクエリを組み立てて検索を実行 できるためデッキメーカーと相性が良い
• 実際のクエリ利用例 ◦ レベル7魔法使い族効果モンスターで破壊以外の除去効果を持つカード ◦ フェアリー・ライフとフェアリー・ Re:ライフを含む水・自然文明のみかつ 5,000円以 下のデッキ ◦ 等々
Architecture
Deck Maker (Nuxt.js) Firestore Firebase Functions カーナベルECサイト Elasticsearch 1. カード・デッキ検索
2. デッキを保存 3. 関数をトリガー 4. 価格データを取得 5. 正規化したデッキ データをWrite ※ 実際のアーキテクチャとは異なります
ECサイトリニューアル(WIP)
ECサイトリニューアル(WIP) • 現行EC老朽化と事業拡大に対応するべく式年遷宮中 • Microservices分割(とはいえ細かく分けすぎないように ) ◦ 販売サイト ◦ 買取サイト
◦ トレカデータサービス ◦ お客様情報管理サービス ◦ 社員管理サービス ◦ 認証基盤 ◦ etc… • 「難しいことを難しくやらない」という姿勢で適切に先端技術を取り込んでいく
Browser Frontend (Next.js) Contour (Envoy) Auth Gateway Argo CD・ Workflows
Cilium OTel Collector Microservice A Microservice B Microservice C
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になるように意識している
Knative • Cloud Runのようなzero-scalingやeventingをEKSでも行いたくて導入 • EKSはNodeの稼働時間に応じて課金されるため、業務時間外の Staging Cluster費用が 勿体無い →
Knativeならリクエストを送るまで Pod数を0にできて経済的 • まだまだ導入企業は少ないものの、小さい開発組織とは相性が良さそう • 余談: カーナベルは日本の会社として唯一 Knative Adoptersにリスティングされてる
Cilium • eBPFで動作するネットワーク制御ツール • Observability ◦ カーネルレベルでCluster内の通信を追えるため、ネットワーク流量や経路の監視が 行いやすい ◦ HubbleというIstioでいうKiali的なService
Map可視化ツールもある • Security ◦ Namespace単位でNetwork Policyを定義でき、Cluster外へのアクセスを制御で きる ◦ アクセス可能な外部サービス (決済プロバイダー, Firebase, Aurora, etc…)をホワ イトリストで定義し、万が一サーバーに侵入されても攻撃者のサーバーへデータを持 ち逃げされないよう制御
Q&A
Hands-on Web Components(Lit)を利用したモダンなUI開発体験
もう少しだけ座学にお付き合いください
そもそもWeb Componentsって何? • 再利用可能なコンポーネントを独自の HTML Tags(Custom Elements)として定義するWebの標 準仕様 • 2011年頃に初めて提唱され、Google主導のPolymer
Projectなどを経て2016年頃から順次ブラ ウザ実装が進む。2020年以降は全てのモダンブラウザで利用可能 • React / Vue / Angular / Svelteといったフレームワークに依存しない = ブラウザネイティブのラン タイムで動作。ポータビリティの高いコンポーネント 定義が可能に • 実際は... ◦ Web標準として汎用性重視の仕様となったため重厚な書き味に ... ◦ LitやSvelte等で定義したコードをcompileして利用するケースが大半
Web Componentsを構成する要素 • Custom Elements ◦ 開発者が独自のHTML Tagsを定義し、挙動をカスタマイズできる • Shadow
DOM ◦ Document APIやCSSの適用対象を特定のスコープ (Shadow DOM)に限定することが可 能になる。各コンポーネントの CSS定義が他の定義と干渉しない! • HTML Template ◦ <template/> <slot/> というフラグメント要素(ページ読み込み時に描画されない DOM要素)の活用 • ES Modules
Web Components in real-life
youtube.com
Material Web
Adobe Spectrum
How to use them?
CodeSandbox Link
Writing Web Components
CodeSandbox Link
CodeSandbox Link 1. HTMLElementを拡張してカ スタムクラスを定義
CodeSandbox Link 1. HTMLElementを拡張してカ スタムクラスを定義 2. shadowRootにHTMLを描 画。getAttributeで親要素から 渡された値を参照
CodeSandbox Link 1. HTMLElementを拡張してカ スタムクラスを定義 2. shadowRootにHTMLを描 画。getAttributeで親要素から 渡された値を参照 3.
customElements.defineで カスタムタグを定義
CodeSandbox Link 1. HTMLElementを拡張してカ スタムクラスを定義 2. shadowRootにHTMLを描 画。getAttributeで親要素から 渡された値を参照 3.
customElements.defineで カスタムタグを定義 4. 定義したカスタムタグを呼び 出し。Attributeで任意の値を指 定
Web Components Data-flow Parent Component Child Component Attributeを経由して値を伝達 CustomEventをdispatchEvent()で発火
Timer Componentを作ろう
Timer Componentを作ろう
Timer Componentを作ろう ① • src/timer.ts を作成 • index.htmlの<body/>内を全て削 除しtimer.tsを読み込み •
<timer-component/>を呼び出し • この時点ではまだ画面に何も表示さ れない
Timer Componentを作ろう ② • HTMLElementを拡張して TimerComponentを定義 • Shadow DOMやattribute監視の設定を 諸々追加
• connectedCallbackに初期化処理を記 述 • customElements.defineを呼んで <timer-tomponent/>というカスタムタ グを定義
Timer Componentを作ろう ②
Timer Componentを作ろう ③ • timer private propertyを定義 • startTimer() ◦
setIntervalで1000ms = 1sご とにHTMLを書き換える ◦ タイマーが終了したら timer-finishedイベントを発火 • stopTimer() ◦ タイマーを初期化する
Timer Componentを作ろう ④ • Event Listenerの設定 • connectedCallback() ◦ 読み込み時の初期化処理
• disconnectedCallback() ◦ オフロード時のリセット処理 ◦ メモリリークの防止 • アロー関数におけるthisのスコープに注 意
Timer Componentを作ろう ⑤ • 呼び出し元でtimer-finishedのイベン トリスナーを定義
Timer Componentを作ろう Check full code in Gist
正直、仕事で使うには辛い・・・ • 現代のUIコンポーネント開発に必須な機能 ◦ Reactに代表される宣言的テンプレート定義 ◦ Vueに代表されるリアクティブなデータバインディング
正直、仕事で使うには辛い・・・ • 現代のUIコンポーネント開発に必須な機能 ◦ Reactに代表される宣言的テンプレート定義 ◦ Vueに代表されるリアクティブなデータバインディング • どちらも自前で実装する必要がある 🔥
正直、仕事で使うには辛い・・・ • 現代のUIコンポーネント開発に必須な機能 ◦ Reactに代表される宣言的テンプレート定義 ◦ Vueに代表されるリアクティブなデータバインディング • どちらも自前で実装する必要がある 🔥
• 手続き的なDOM管理 ◦ element.innerHTMLで一括更新を行うためパフォーマンスも悪い • リアクティビティの担保とデータバインディング ◦ class propertyにtemplateが依存した状態でpropertyが更新された場合、明示的に DOM の更新や参照部分の再計算を行う必要がある → 依存ツリーやbatch update queueの自 前管理が必要
None
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
Lit Sandbox Link
LitでTimer Componentを作ろう litをインストール
LitでTimer Componentを作ろう tsconfig.jsonにオプションを追加
LitでTimer Componentを作ろう ① • src/lit-timer.ts を作成 • index.htmlの<body/>内を全て削 除しlit-timer.tsを読み込み •
<lit-timer-component/>を呼び 出し • この時点ではまだ画面に何も表示さ れない
LitでTimer Componentを作ろう ② • LitElementを拡張する • @customElement decoratorでラップ • 親から受け取るdurationに@property
decoratorを付与 • render() ◦ reactive propertyの変更に応じ て自動で実行される描画処理 ◦ html関数にtagged template literalを渡して宣言的に定義
LitでTimer Componentを作ろう ③ • timer private propertyを定義 • startTimer() ◦
setIntervalでduration propertyを更新。HTMLの書き換え は行わない ◦ タイマーが終了したら timer-finishedイベントを発火 • stopTimer() ◦ タイマーを初期化する
LitでTimer Componentを作ろう ④ • Event Listenerの設定 • @click ◦ onClickの糖衣構文
◦ template内で直接 addEventListener相当の処理を定義 可能 = 宣言的定義 ◦ removeEventListenerも不要
LitでTimer Componentを作ろう ⑤ • 呼び出し元でtimer-finishedのイベン トリスナーを定義
Lit Timer Componentを作ろう Check full code in Gist
None
ここまでのまとめ
前半の部 まとめ • Web Componentsを利用することで汎用的なカスタムタグを利用することができる • Litを利用することでより宣言的かつ生産的なコンポーネント開発が行える ◦ reactive property
◦ declarative render function ◦ etc… • 後半の部ではLitを利用してDeck Makerのデッキ埋め込み機能を作っていきます
休憩時間 (~13:30)
後半の部: デッキ埋め込み機能を作ってみよう
完成イメージ Storybook Link
作業の流れ GitHub Repository
お題①: DMDeckInfo • デッキの基本情報を表示するコンポーネントを作る (完成系) • デザインは雰囲気で。paddingや細かいfont-sizeは特に指定しません • property: ◦
deckData ← APIから取得するデッキデータ。今回は mock値で代用 • 表示する情報: ◦ サムネイル ◦ レギュレーション ◦ 更新日 ◦ デッキ名 ◦ ユーザー名 ◦ 閲覧数 レギュレーションの表示ルール • none → 殿堂ゼロ • advance → アドバンス • 2block → 2ブロック • party → デュエパーティー • Original → オリジナル
お題②: DMTabs • デッキの表示領域を切り替えるコンポーネントを作る (完成系) • property: ◦ deckData ←
APIから取得するデッキデータ。今回は mock値で代用 ◦ currentTab ← 現在表示中のタブ • dispatchEvent: ◦ change ← タブが選択されたら発火 ▪ new CustomEvent(‘change’, { detail: targetTab }) • その他仕様: ◦ currentTabはactive classを付与 ◦ メイン/GR/超次元はラベルの横に枚数を表示する ◦ deckData.dorumagedonがtrueの時のみドルマゲドンのタブを表示する ◦ deckData.zeronがtrueの時のみ零龍のタブを表示する
お題③: DMDeck • 実際にサイトから呼び出されるデッキ取得 & 表示コンポーネント(完成系) • property: ◦ dmDeckId
← デュエマデッキID • state: ◦ currentTab ← 現在表示中のタブ ◦ 参考: Lit - Internal reactive state • methods ◦ changeTab ← DMTabsコンポーネントのchange eventをトリガーに実行。受け取った値 でstateを更新する • おまけ ◦ Storybook上でdmDeckIdを変更た際にデッキの再取得 & 再描画を行うには? ◦ 参考: Lit - Reactive update cycle
自サイトへの埋め込み方法
自サイトへの埋め込み方法
自サイトへの埋め込み方法 • vite buildが実行されるとdist/assets/index-<revision>.jsが生成される • 上記のindex.jsをサイトに読みこんで <dm-deck />を呼ぶだけ • --assetsInlineLimitで指定のbyte数以下の画像ファイルはインライン化できる
外部サイトへの埋め込み方法
外部サイトへの埋め込み方法 • 外部のサービスプロバイダ (note, アメーバブログ, はてなブログ, etc…)が<dm-deck/>の仕様 を把握するのは流石にムリ • デッキメーカーのnote埋め込み機能はどのように実装されているのか?
oEmbed • oembed.comで定義されている汎用的なコンテンツ埋め込み仕様 • 2008年ごろに提案され、Wordpressをはじめとする複数企業によってメンテナンス中 • 埋め込み可能なコンテンツ : ◦ photo
◦ video ◦ link ◦ rich ← htmlの埋め込みが可能。Deck Maker(ガチまとめ)はこれを利用している
oEmbedのフロー 1. 埋め込みURLへアクセス
oEmbedのフロー
oEmbedのフロー 1. 埋め込みURLへアクセス 2. embed endpointをheadで伝達
oEmbedのフロー
oEmbedのフロー 1. 埋め込みURLへアクセス 2. embed endpointをheadで伝達 3. embed endpointへアクセス 4.
Rich TypeのJSONを返却
oEmbedのフロー embed.json
oEmbedのフロー 1. 埋め込みURLへアクセス 2. embed endpointをheadで伝達 3. embed endpointへアクセス 4.
Rich TypeのJSONを返却 5. JSONに指定されたiframeを描画 6. iframe srcで指定されたHTMLを返却
oEmbedのフロー iframe src link
本日はここまで
長時間お付き合いいただき ありがとうございました!