au Web ポータルにおけるフロントエンドの取り組み。 チーム学習とは、チームプレイとは。
au Webポータルにおけるフロントエンドの取り組み未学習領域におけるチーム{学習,プレイ}とは2019-04-17 BIT VALLEY -INSIDE- Vol.8
View Slide
Who{{"name""name" :: "武田 諭""武田 諭",,"social""social":: "@tkdn""@tkdn",,"from""from" :: "株式会社 mediba""株式会社 mediba",,"dept""dept" :: "CD本部創造開発部/ものづくり推進部""CD本部創造開発部/ものづくり推進部",,"work""work" :: "フロントエンドエンジニア""フロントエンドエンジニア",,"word""word" :: "ブラウザが主戦場""ブラウザが主戦場"}}
Who1980年生まれ, 38歳2003~2013俳優業2013~2017エンジニア転向、受託開発など2017~ mediba,入社2年目
今日の話はau Webポータルのリニューアルにおける取り組み未学習領域におけるチーム学習チームにおける学習に必要なものはなんだろうテクニカルなことにはあまり触れません
アジェンダau Webポータルリニューアルに際して、1.何を変えたか開発チームの体制,チーム再編による技術刷新2.どう取り組んでいったか学習における課題,具体的な取り組み3.チームは,わたしは何を学べたか
何を変えたか#1開発チームの体制
FromFront-End : Server-Side = 4 : 8
ToFront-End : Back-End = 9 : 3
比率の変更の理由事業成長に伴う施策はフロントエンドがメイン人的リソースの効率化を行うため,比率の変更技術的な成長要素と市場価値の創出
フロントエンド?ブラウザ・クライアントアプリケーションコードBFF(API)クライアントサイドのトラブルシュートまでの範疇を広義のフロントエンドととした
何を変えたか#2チーム体制変更による技術刷新
FromServer-Side: Yii Framework(PHP)Front-End: jQuery, Backbone.jsServer: apache, and other middlewaresInfra: self-uncontrollableな環境
チーム体制変更に見合った技術選定広義のフロントエンド領域において境界を失くす言語の違いによるコンテキストスイッチを減らす共通言語によりappコミュニケーションコストを下げる
To✏ : TypeScriptTypeScript: Next.jsNext.js⚛ : React/ReduxReact/Redux, w/ reselect, redux-thunk: expressexpress: graphql-yogagraphql-yoga, express-basedInfra: AWSへ移管, ECR + ECS/Fargate...
TypeScript,全員ほぼ未経験React/Redux,全員ほぼ未経験Node.jsによるフロントサーバ,全員未経験GraphQL,何それ美味しいのどう考えても風呂敷広げすぎ問題さてどうしていくか…
どう取り組んでいったか#0チーム学習における課題を考える
考える前に各スキルセット整理旧フロントエンド渉外的なやりとりにおいてバリューを発揮コミュニケーションブリッジとなるシーンも多いappエンジニアとしてのハードスキルが不足
各スキルセット整理旧サーバサイド経験値・ハードスキルが高いサーバサイド PHPを触っていた人たちクライアント・ブラウザについては弱い
どのように学習していくかを考えるバックグラウンドが違うメンバーがゼロベースの新しいスタックにどう効率的に学習していくのか
初手:とにかく伝搬自ら吸収したものをとにかく伝搬しまくるドキュメントを和訳して Slackで展開=>届け、誰かにPoCを実装,コードで展開=>読んで、コードを突然あらわれるライフサイクルメソッドおじさん※ React 16.3~ lifecycle methodが deprecatedになるタイミング=>ついてきてー
知っていることを提供できてもメンバーに伝播できているとは限らないさて二手目、どうしようか…
どう取り組んでいったか#1がんばらないTypeScript
Why TypeScript ?クラスベースの OOP言語ならサーバーサイドの人も入りやすいはず既存のフロントエンドはJSを触ってきている(TypeScriptは JSのスーパーセットやろ クチャクチャ
触ってみて型定義、なにそれ美味しいの?全然型通らない…なぜコンパイルできない…VSCodeが赤くなって何がなんだかわからない…
プロジェクト初期 @__gfx__さんに相談した< 型付けをがんばらない
がんばらないTypeScriptのはじめ方 -角待ちは対空anyでもいいじゃない。詰むより作る、前に進む慣れてくると良さや勘所がだんだんわかってきたanyで逃げたところもきっちり型付けしだしたTypeScript…これはいいものですね
静的なコンポーネントからAtomic Designで構成したコンポーネント tsxを静的に実装Props,ローカル Stateの型付け, interfaceの規約などを作り慣れていった序盤でTSLintルール整備pre-commit hookによりコードの一貫性は最初から保てた
ある程度慣れてからのメンバーのTypeScriptへの感想JavaScriptというゆるふわな言語を TypeScriptがガチッとフォローしてくれて良いFlowを書いていた時よりもガッツリと型を書いている感じがあって最高VSCodeの補完が最高すぎて生産性が爆上がりした型定義する時に逃げることがあった(anyでもOKという安全性も大事)
厳格なスタートを切らない学習序盤からゆるふわでスタートしても最終的に変更・修正できる容易性の方が重要
どう取り組んでいったか#2Reduxとペアプロ
"Reduxは学習コストが高い"知ってる
2, 3名のチーム別に伝達するフェーズReduxおじさんによる概念説明アプリケーションをグローバルに状態管理できる Pub/Subパターン!カスタムイベントあるじゃないですか!?イベント来たら反応するめっちゃ便利なオブザーバー!なんかすごい便利なやつ(語彙力
概念的なものは伝わったという意味では効果はあったのかもしれないが実装レベルに落とせていないこれは思ったより実装までのリーチがだいぶ長いのでは…?React / Reduxの習熟度が高いメンバーがジョイン
習熟度の高いメンバーを中心にペアプロを行った※ 一般的なペアプロとは乖離があるかもしれません。1.朝会で機能ベースでペアを決める2.ペアで時間を決めて自由にスタート3. VSCode LiveShareを使う4.ドライバー・ナビゲーターはなんとなく5. 3,4時間使って集中的に
広義のFEチーム内でペアプロをする利点得意なフィールドによって交代できる得意なフィールドであれば検索能力も高く参考資料として SlackにURL貼り付けGraphQL側の Logicって? Resolverって?違うフィールドへの理解を深められるメリット適宜交代することで得られるスピード感もある
雑談から得られる利点Techな話題が多くなり自然とそんな会話になりやすく雑談の質が上がる共通関数作りたくなる派,時期尚早まだ共通化しない派など個人の特性がわかる考え方の違いが出てきたりなど初めて知る部分も多い
⏱ 時間的な制約の中で得られる利点機能実装の本質に効率的に近づける個人でやるとリファクタしたくなるところを、今は機能を実装しようというスタイルになる一人で出来ることは後回し、機能実装を優先できる一人だと不要な yak shavingをやってしまいがちだが抑止できる
デメリット口頭伝承スタイルになるのでドキュメントが残らない知見がどうしてもペアを組んだエンジニア同士で留まってしまうPRも合意が得ているのでレビューを通さないようなスタイルだったそれら度外視しても、ペアプロいいものですね
ある程度慣れてからのメンバーの感想Redux関連で詰まってることが多かったので LiveShare /ペアプロで進捗がかなり上がった理解してくると便利に思えてきた自分はペアプログラミングが結構効いている、質問する時間も省けたり、会話しながらだと理解力も全然違ってとにかく効率良く学べた
自学自習には限界がある対話しつつ機能を作っていくほうがチームには効率的なシーンがある雑談、めっちゃ大事ペアプロ、めちゃくちゃいいものですね
どう取り組んでいったか#3React client tuningと信頼
dev環境も出来てきたしデプロイしてみたらインタラクションがもっさりしている…リニューアル前のサクサクした感じがない…スクロールによるメモリ不足でブラウザタブが落ちる始末…機能実装優先で細部のパフォーマンスまで意識出来ていなかった
計測によるもっさり検出もっさりの感覚値をきちんと確認Chrome DevTools Performanceタブユーザインタラクションが発生した後に出ている violation(違反)をまず拾い上げる不快感は遅延したフィードバックが主な原因(200msから違和感)
いつviolationが出る?ユーザイベント(click, touchend, scroll...)によるハンドラ実行完了まで時間がかかったJavaScript実行時に強制的に re owが走ったdocument.writeを使用したイベントに対して非効率なハンドラのアタッチが行われた ... etc
メンバーに伝搬習熟度の高いメンバーがサンプルになるようなPRを作成勘の鋭いメンバーにチューニングの肝を伝搬計測・仮説(改修実装)・検証、根気のいる作業なので単独作業とし成果をPRでレビュー
violationどう潰す?インタラクションに紐づくイベントへアタッチされた処理から見ていくことにしたPerformanceタブで採取した情報を元手にハンドラを追っていく詳細計測はUser Timing APIを使った計測(React v16から可能)
パフォーマンスを意識せず富豪実装していった結果ほとんどがコンポーネントのムダなアップデート主だった要因としてはスタティックなコンポーネント実装時にすべて FCで実装していたため
マズそうなコンポーネントを洗い出し適宜 React.memo化、ムダなアップデート抑止shouldComponentUpdateで適切にアップデートを抑止onClickに arrow-functionをそのまま渡していないか( tslint-react: jsx-no-lambda rule)shallow equalの比較よりも FCで再レンダリングした方がコストが低い場合があるので注意 ... etc
勘所を抑えたメンバーが大改善
UIコンポーネントから大量に作ったのが仇となった後半でパフォーマンス等の整合性取るのはなかなか大変信頼ベースでタスクを委ねる
チームは,わたしは何を学べたかlearn and delegate
個人の気づき伝播だけでは空回りしてリーチしない自分が独習できた環境とは何かを思い出した人は最初から自学自習できるわけではない外的要因や環境の上で学習できたに過ぎない
ゼロベースからのチーム{学習,プレイ}とは導入を容易に、障壁を軽減させる環境を整備することから始めよう
1.最初からルール立てて厳格なスタートを切らない学習序盤からゆるふわでスタートしても最終的に変更・修正できる容易性の方が重要2.ペアプロ、めちゃくちゃいい個人の自学自習には限界がある対話しつつ機能を作っていくほうがチームには効率的なシーンがある雑談、めっちゃ大事3.後半は信頼ベースでタスクを委ねよ
リニューアル自身の成功・失敗少しだけクライアントパフォーマンスの話
au Webポータルですが実は現在クライアントサイドでReactが動いていませんCSRはリニューアル以前の Backbone.js, jQueryで動いています
理由リニューアル後の事業売上=広告収入が減少クライアントパフォーマンスの影響と思われる売上としての選択からReactによる CSRから以前のスタックへ
何が問題だったかReact.hydrateによるイベントへのアタッチ、クライアントで必要な Fetchに時間がかかり UIが遅延それらと広告 3rd partyスクリプトとの共存においてどうしてもクライアントサイドのパフォーマンスを上げられなかった
リニューアル後のパフォーマンス値実は数字が良かったりする
TTFBの向上 => CDNに Akamaiを選択FirstPaint FCP/FMPともに向上 => React SSRTimeToInteractiveの低下 =>アタッチ, Fetchによる UI遅延 e.g.タブ遷移
身内自慢DataStudioとGASでWebPagetestの計測結果をグラフ化する | mediba Creator× Engineer Bloggas-webpagetestでWebPagetestのパフォーマンス計測を自動化、可視化する | Web Scratch
広告表示の優先度を上げるために事前知識:おおよそ 3rd partyはメインスレッドの処理ブロックを引き起こす(`document.write`など)アプリケーションコードをコールバックキューに積んで遅延実行=>効果はある。UI遅延を生む。それはそう。オススメしないで 3rd partyを投機的読み込み=>効果大。ブラウザの実行優先度を理解するのが良いかも
Priority on Browser(Chrome)AddyOsmani.com - JavaScript Loading Priorities in Chrome
数値としてはどのくらい盛り返せたのかリニューアルリリース、その後チューニング for広告、CSR等変更してリリース左:リニューアル前,右:諸々変更を加えてのチューニング後リリース初期描画, FCP/FMPいずれも向上元々 Akamaiの TTFBが早かったのでさらに後続の数値が良くなるUI完了も早いので準じて広告描画との棲み分けが最適化広告売上も4月に入ってきて回復している(まだ経過観察中)
悔しい。あきらめねーぞReact CSRに戻すためにはReact Concurrent Mode = Async RenderingScheduling in ReactUI =メインスレッドをブロックすることなくコンポーネントの描画を適宜スケジューリングできるとみんな幸せそう
以上ありがとうございました
天下一品 高円寺店 (てんかいっぴん) -高円寺/ラーメンづゅる麺池田 (づゅるめんいけだ) -目黒/つけ麺自家製麺 MENSHO TOKYO -後楽園/つけ麺
宣伝フロントエンドランチここ 8Fでフロントエンドランチを毎週水曜やってます(去年6月から初めて今日で39回目でした)Slackにてチャンネルを共有できます参加のご希望があれば声かけてください!フロントエンドランチ - medibaWe are hiring.Wantedly, Findy... FE募集してます