負債が溜まったレガシーフロントエンド画面を Vue.js でリプレイスした話
by
t0yohei
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
負債が溜まった レガシーフロントエンド画面を Vue.js でリプレイスした話 Vue Fes Japan Online 2022 - 2022/10/16
Slide 2
Slide 2 text
自己紹介 ● とよへい ( @t0yohei ) ● 株式会社クラウドワークス ○ Web エンジニア ● アニメとコーヒーが好き ● Vue.js / Ruby / PHP
Slide 3
Slide 3 text
想定する聞き手 ● レガシーなフロントエンドに向き合っている方 ● Vue.js での開発ノウハウに興味がある方 ● 不思議なものがみたい方
Slide 4
Slide 4 text
Midjourney
Slide 5
Slide 5 text
アジェンダ ● なぜ Vue.js 化を実施したのか ● どういう作戦で進めていったか ● 品質管理について ● 難しかったこと ● まとめ
Slide 6
Slide 6 text
なぜ Vue.js 化を実施したのか
Slide 7
Slide 7 text
No content
Slide 8
Slide 8 text
クラウドワークスのフロントエンドについて ● クラウドワークスは、10年ほど前に Rails + jQuery の構成で生まれた ● 新規画面は Vue.js で作成されているが、jQuery を使った古い画面がかなり残って いる
Slide 9
Slide 9 text
クラウドワークスのフロントエンドが抱えている課題 ● 見た目を変えたいだけなのにバックエンドの Rails をいじる必要がある ● フロントエンド、バックエンドの分業がしにくい ● jQuery を書きたくない
Slide 10
Slide 10 text
これらの課題を Vue.js 化で解決しよう
Slide 11
Slide 11 text
Vue.js 化して既存画面を もっと改善しやすくしよう
Slide 12
Slide 12 text
どういう作戦で進めていったか
Slide 13
Slide 13 text
Vue.js 化の大まかな方針 ● 最終的には全画面を Vue.js 化したい ● 時間的な制約もあるので、優先順位が高いものから対応していく
Slide 14
Slide 14 text
優先順位はどうやってつけよう
Slide 15
Slide 15 text
「Vue.js 化して既存画面を もっと改善しやすくしよう」
Slide 16
Slide 16 text
将来的に改善したくなる可能性が 高い画面を優先する
Slide 17
Slide 17 text
ユーザーのアクセスが多い 一般ユーザー向け画面
Slide 18
Slide 18 text
優先順位の考慮から外した観点 ● UIの変更が頻繁に行われている画面 ○ 特定の理由で更新されているだけ (バナー更新とか) ○ 単に手を入れるのが簡単
Slide 19
Slide 19 text
両方大事にした観点 ● 対応が簡単な画面をたくさん改善 ○ ユーザーに対するインパクト ● 対応が難しい画面にじっくり挑む ○ 長期的な改善に対するインパクト
Slide 20
Slide 20 text
ひとまずの Vue.js 化を行う画面 ● 練習用の管理画面 × 1 ● 一般ユーザー向けの簡単な画面 × 2 ● 一般ユーザー向けの難しい画面 × 1 ● (これらの画面の対応が終わったら、体制を整えて Vue.js 化を継続する)
Slide 21
Slide 21 text
実装のスコープ
Slide 22
Slide 22 text
「Vue.js 化して既存画面を もっと改善しやすくしよう」 という目的に注力して、色々やりすぎない
Slide 23
Slide 23 text
何をやらないか(スコープ外) ● CSSフレームワークを外す ● バックエンドに API を生やして、API 経由でデータのやりとりをする ● その他コストがたくさんかかりそうなことは無理にやらない
Slide 24
Slide 24 text
品質管理について
Slide 25
Slide 25 text
各種ツールと人力で品質を担保 ● Storybook ○ コンポーネント毎の動作を担保 ● VRT(Visual Regression Testing) ○ 見た目の確認と、置き換え途中でデグレしていないことを担保 ● vue-test-utils ○ API 通信などの動作を担保 ● 手動テスト ○ 統合的な動きを担保
Slide 26
Slide 26 text
No content
Slide 27
Slide 27 text
Storybook
Slide 28
Slide 28 text
No content
Slide 29
Slide 29 text
No content
Slide 30
Slide 30 text
VRT (Visual Regression Testing)
Slide 31
Slide 31 text
No content
Slide 32
Slide 32 text
No content
Slide 33
Slide 33 text
● フロントエンド開発体験向上のために VRT を導入してみた ● crowdworks.jp のフロントエンド活動を振り返る 2021 詳細はテックブログに
Slide 34
Slide 34 text
E2E テストは不採用 ● 負債が溜まった画面の E2E テスト、とても辛さそう ● 一括のリプレイスを考えていたので、メリットがそこまで多くなさそう ● (リプレイス全体を通して大きな問題は発生しなかったのでヨシ)
Slide 35
Slide 35 text
難しかったこと
Slide 36
Slide 36 text
Rails, jQuery のコードを Vue.js っぽいコードに書き換える
Slide 37
Slide 37 text
具体的には ● 命令的 UI を宣言的 UI にする ● Rails, jQuery のコードを Vue.js, TypeScript のコードに書き換える ● バックエンド(Rails)からフロントエンド(Vue)に適切な値を引き渡す
Slide 38
Slide 38 text
例: 仕事の予算を表示する部分
Slide 39
Slide 39 text
置き換え前のコード
Slide 40
Slide 40 text
何らかの html を生成して挿入する ここで生成された html を挿入する
Slide 41
Slide 41 text
置き換え後のコード
Slide 42
Slide 42 text
No content
Slide 43
Slide 43 text
宣言的に書く
Slide 44
Slide 44 text
script setup を使って Vue.js と TypeScript で実装
Slide 45
Slide 45 text
これいるの...?ってコードが 埋まってる
Slide 46
Slide 46 text
具体的には ● A/B テストの残骸 ● どこからも参照されてなさそうなコード ● 新しく作成されるデータでは付与されることがないラベル
Slide 47
Slide 47 text
実は前から壊れていた🙄
Slide 48
Slide 48 text
No content
Slide 49
Slide 49 text
本体リリースに先駆けてお掃除
Slide 50
Slide 50 text
とにかく機能が多い
Slide 51
Slide 51 text
中ボスが 50 人くらいいるイメージ
Slide 52
Slide 52 text
機能ごとにコンポーネントを分けてひたすら作成
Slide 53
Slide 53 text
工夫: Containar Component で統制を取りやすく ● style を持たない Vue コンポーネント ● 自身が含むプレゼンテーションコンポーネントにデータを受け渡す ● バックエンド API とやりとりするためのインターフェースを持つ
Slide 54
Slide 54 text
style を持たない バックエンド API とやりとりする ためのインターフェース プレゼンテーション コンポーネントにデータを受け渡す
Slide 55
Slide 55 text
工夫: Layout Component でスタイル定義を分離 ● script を持たない Vue コンポーネント ● slot を使ってコンポーネントを入れ込む
Slide 56
Slide 56 text
slot を使って コンポーネントを入れ込む script を持たない Layout Component
Slide 57
Slide 57 text
共通のスタイル定義を切り出すとかもできる 共通のスタイル定義を切り出す
Slide 58
Slide 58 text
どうして...ってコードがある
Slide 59
Slide 59 text
気になるボタン(Watchlist Button)
Slide 60
Slide 60 text
No content
Slide 61
Slide 61 text
修正前の実装
Slide 62
Slide 62 text
watchlist のデータ(json)を非同期で一 括で取ってくる 取得したデータ(json)に html が含まれ ているので、id が一致した仕事に対して その html を埋め込む watchlist button を埋め込む div が仕 事ごとに用意されている
Slide 63
Slide 63 text
取得したデータ(json)に html が 含まれているので?
Slide 64
Slide 64 text
No content
Slide 65
Slide 65 text
json に埋め込まれる html (※ 見やすさのために本来存在しない改行追加しています)
Slide 66
Slide 66 text
No content
Slide 67
Slide 67 text
json として html を受け取って、 その html を dom にぶち込んでる
Slide 68
Slide 68 text
「気になる」ボタンが押された時はもちろん DOM の埋め込み直し
Slide 69
Slide 69 text
JSON 色つけですらなく、 DOM をそのまま埋め込み職人
Slide 70
Slide 70 text
(余談) Q. watchlist の追加に失敗したら どうなるでしょう?
Slide 71
Slide 71 text
A. Status Code: 200
Slide 72
Slide 72 text
status コードは甘え。 やる気があるなら payload の文字列で 結果を判定しろ
Slide 73
Slide 73 text
どうしようこれ
Slide 74
Slide 74 text
そもそもどういう感じに なっていたら嬉しいか
Slide 75
Slide 75 text
期待する動作 1. 画面初期化時は ajax でボタンの html(json) を取ってくるんじゃなくて、 watchlist の状態だけもらっておいて Vue.js 側でボタンの出し分けをする 2. 気になるボタンが押されたら、追加リクエストを送る 3. 追加された watchlist の id をレスポンスで受け取り、取り消しボタンを表示する 4. 取り消しボタンが押されたら、2で取得した id をつけて取り消しリクエストを送 る
Slide 76
Slide 76 text
課題は何か ● 取り消しリクエストには watchlist の id が必要 ● 現状の watchlist 追加 API だと、レスポンス json の html の中に watchlist の id が埋まって いて取り出しにくい
Slide 77
Slide 77 text
どうやって解決したか
Slide 78
Slide 78 text
現状の watchlist 追加 API のレスポンスに、 追加された watchlist の id 加えてあげたら、 影響少なそうだし実装の手間少ないし、 やりたいこと実現できるし良いじゃん!!😈
Slide 79
Slide 79 text
つまり レスポンスに新しく追加した watchlist_id を足して ● html ● message ● watchlist_id (NEW!) の 3 本立てで返してあげるようにする
Slide 80
Slide 80 text
json に html が含まれている状態を 放置することになるけどいいの...?
Slide 81
Slide 81 text
No content
Slide 82
Slide 82 text
という訳で ついでに成功したかど うかも返すことに
Slide 83
Slide 83 text
めでたし!!!!
Slide 84
Slide 84 text
まとめ
Slide 85
Slide 85 text
振り返り ● Vue3 + TypeScript は開発体験が良くて、書いていて楽しい ● レガシーフロントエンドの Vue.js への置き換えは、単純にはできなくて骨が折れる ● 削れる機能は削って、もっと楽したかった ● どうして...ってコードは、一周回って変な笑いが出る
Slide 86
Slide 86 text
大事なこと ● 目的を明確にして、やらないことを決める
Slide 87
Slide 87 text
やめないこと
Slide 88
Slide 88 text
Special Thanks ● OD さん ● yamanoku さん
Slide 89
Slide 89 text
Thank you for listening !!