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
フロントエンドの複雑さに耐えるため実践したこと / readyfor-nextjs-first
Search
Takepepe
February 05, 2021
Technology
25
11k
フロントエンドの複雑さに耐えるため実践したこと / readyfor-nextjs-first
【READYFOR】実践!フロントエンド分離戦略::発表資料
https://readyfor.connpass.com/event/198730/
Takepepe
February 05, 2021
Tweet
Share
More Decks by Takepepe
See All by Takepepe
ServerAction で Progressive Enhancement はどこまで頑張れるか? / progressive-enhancement-with-server-action
takefumiyoshii
7
780
App Router への移行は「改善」となり得るのか?/ Can migration to App Router be an improvement
takefumiyoshii
8
3k
フロントエンドの書くべきだったテスト、書かなくてよかったテスト
takefumiyoshii
39
15k
Webフロントエンドのための実践「テスト」手法 CodeZine Night #1
takefumiyoshii
24
8.3k
Next.js でリアーキテクトした話 / story-of-re-architect-with-nextjs
takefumiyoshii
12
8.6k
より速い WEB を目指す Next.js / nextjs-make-the-web-faster
takefumiyoshii
54
19k
Redux の利点を振り返る
takefumiyoshii
26
8.6k
Type-only Migrate by AST
takefumiyoshii
1
620
- Regular expression & Type - Naming Rule Linter
takefumiyoshii
1
370
Other Decks in Technology
See All in Technology
LeSSはスクラムではない!?LeSSにおけるスクラムマスターの振る舞い方とは / Scrum Master Behavior in LeSS
toma_sm
0
210
エンジニア向け会社紹介資料
caddi_eng
14
270k
トークナイザー入門
payanotty
2
1k
エムスリー全チーム紹介資料 / Introduction of M3 All Teams
m3_engineering
1
320
Deno Deploy で Web Cache API を 使えるようになったので試した知見
toranoana
1
110
Qdrant を用いた検索改善施策の紹介 / Search Engineering Tech Talk 2024 Summer
visional_engineering_and_design
1
210
それでもやっぱり ExpressRoute が好き!
skmkzyk
0
380
コード✕AIーソフトウェア開発者のための生成AI実践入門~
yuhattor
4
860
Amplify Gen 2ではじめる 生成AIアプリ開発入門
tsukuboshi
0
240
CData Virtuality を活かせるキーシナリオと製品デモ
cdataj
0
230
LINE-ChatGPT 倫理問題を整理する全力肯定彼氏くん [LuC4]に訪れたサービス開始以来の最大の危機
o_ob
2
160
受託開発でもアジャイル開発できました / Agile in Contract Development
takaking22
9
4.6k
Featured
See All Featured
Designing the Hi-DPI Web
ddemaree
280
34k
What's new in Ruby 2.0
geeforr
341
31k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
228
52k
Fontdeck: Realign not Redesign
paulrobertlloyd
81
5.2k
Building Your Own Lightsaber
phodgson
102
6k
Thoughts on Productivity
jonyablonski
67
4.2k
How GitHub (no longer) Works
holman
311
140k
Agile that works and the tools we love
rasmusluckow
327
21k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
Building a Scalable Design System with Sketch
lauravandoore
459
33k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
39
2.1k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
327
21k
Transcript
READYFOR x Next.js フロントエンドの複雑さに耐えるため実践したこと @ Takepepe
READYFOR フロントエンド分離のゴール ▪ BE/FE の責務をわけ、疎結合とすること ▪ 時代に即したベストプラクティスを追求できること #readyfor_meetup
READYFOR フロントエンド分離のゴール これまでモノリスだった RoR の アプリケーションサーバーは APIサーバーへ。 View はJS(TS)だけで完結する姿へ…
#readyfor_meetup
READYFOR フロントエンド分離のゴール Next.js はこういった背景のプロダクトで選ばれる、 筆頭の選択肢となりました。 静的キャッシュ恩恵・ゼロコンフィグ、 SSR ハイブリッドなど、要件に合わせやすいです。 #readyfor_meetup
参画の経緯と当時の状況 READYFOR からお誘いをうけ 委託参画したのが昨年4月。 この10ヶ月間で2つの Next.js 案件 立ち上げをお手伝いしました。 #readyfor_meetup
参画の経緯と当時の状況 すでに分離戦略が敷かれていたため、 わたしの担当は明確でした。 デザインシステム(READYFOR Elements)を利用 して、Next.js App を構築することです。 #readyfor_meetup
参画の経緯と当時の状況 ▪ RoR アプリケーション一部に、react_on_rails ▪ READYFOR Elements が仕上がっていた ▪ Next.js
製の PoC があった #readyfor_meetup
参画の経緯と当時の状況 Next.js / SPA 化にともない、フロントエンドが抱える 表示ロジックが複雑になることが想定されました。 その複雑さを乗り越える設計・実装を どの様に行ったのかを、本日お話します。 #readyfor_meetup
Redux の参照秩序
はじめに手掛けた「実行者SPA」は、 細かな UI の部分再描画が頻出する要件でした。 状態管理ライブラリに Redux を選定しました。 Redux を選んだ理由 #readyfor_meetup
Redux を選んだ理由 ▪ 算出値のメモ化と、部分再描画に優れている ▪ devtools が他ソリューションと比較し充実している ▪ integration test
が実施しやすい #readyfor_meetup
Redux は「秩序が生まれやすい」と定評がありますが、 使い方次第では「無秩序」になりやすいものです。 採用の際には、ガイドラインが必要です。 Redux の懸念点 #readyfor_meetup
参照秩序 のガイドライン ファイル構成は Re-ducks パターンとしました。 関心範囲を境界とし、 Module 毎で管理。 ├── redux
├── A ├── B ├── C ├── D ├── index.ts ├── reducers.ts └── store.ts #readyfor_meetup
参照秩序 のガイドライン ├── redux ├── A ├── B ├── C
├── D ├── index.ts ├── reducers.ts └── store.ts ファイル構成は Re-ducks パターンとしました。 関心範囲を境界とし、 Module 毎で管理。 Module #readyfor_meetup
参照秩序 のガイドライン ├── redux ├── A ├── B ├── C
├── D ├── index.ts ├── reducers.ts └── store.ts Module の内訳は以下のとおり。 State を軸とした定義を保有します。 state.ts / reducer.ts / actions.ts selectors.ts / thunks.ts #readyfor_meetup
参照秩序 のガイドライン ├── redux ├── A ├── B ├── C
├── D ├── index.ts ├── reducers.ts └── store.ts この Module 同士は、 参照関係をもつことができます。 #readyfor_meetup
参照秩序 のガイドライン ├── redux ├── A ├── B ├── C
├── D ├── index.ts ├── reducers.ts └── store.ts 例えば「A」で発行された 「A」のための Action を、 「C・B」でも購読する、 という参照関係です。 #readyfor_meetup
参照秩序 のガイドライン ├── redux ├── A ├── B ├── C
├── D ├── index.ts ├── reducers.ts └── store.ts この参照秩序が保たれなければ、 スパゲティコードが生まれます。 Reducer と Selector で、 この参照捻れは発生し得ます。 #readyfor_meetup
参照秩序 のガイドライン 参照秩序は公式ガイドの Basic State Shape を参考に、 「Module prefix」で明文化しました。 https://redux.js.org/recipes/structuring-reducers/basic-reducer-structure#basic-state-shape
#readyfor_meetup
Module prefix ?
参照秩序 のガイドライン Api** App** UI** Page** Module prefix を4つに区分。 prefix
により、参照権限が異なります。
参照秩序 のガイドライン(prefix: Api***) Api** App** UI** Page** API レスポンスを「取得・保持」するのみ。 API
path と1対1で設け「別 Module は参照しない」
参照秩序 のガイドライン(prefix: App***) App** UI** Page** アプリケーションで横断的に利用する値を管理。 また「API・App」Module しか参照できない。 Api**
参照秩序 のガイドライン(prefix: UI***) UI** Page** Global UI に関連する状態しか持たない。 また「API・App・UI」しか参照できない。 Api**
App**
参照秩序 のガイドライン(prefix: Page***) Page** 全ての値と Action を参照できる。 Page Component と1対1。
Api** App** UI**
参照秩序 のガイドライン(prefix: Page***) 「下流 Module が上流 Module を参照する」という、 シンプルな命名規則による参照秩序を設けました。 Api**
App** UI** Page** 上流 下流
このガイドラインの目的は、 参照権限を限定することで、 責務の所在を明確にすることです。 参照秩序 のガイドライン #readyfor_meetup
責務の所在地が明確であれば、 設計の属人化が最小限になります。 そして、必要な責務のみが下流に降りてきます。 参照秩序 のガイドライン #readyfor_meetup
参照秩序 のガイドライン Page** この関係とすることで、特定ページ専用の「Page**」Module は、 特定ページの処理のみに、専念することができます。 Api** App** UI**
参照秩序 のガイドライン ▪ 実装中に異常な参照捻れに気付ける ▪ コンテキスト理解が容易くレビュー負荷も下がる 命名規則だけで、開発体験はよりよくなる! #readyfor_meetup
Cypress 実践 BDD
Cypress で実践する BDD 表示分岐ロジックが複雑になることが想定されたため、 integration テストは不可欠としていました。 そのため、後発の Prj は立ち上げ初期から BDD
を採用しました。 #readyfor_meetup
Cypress で実践する BDD これから作成しようとするプログラムに 期待される「振る舞い」や「制約条件」、 つまり「要求仕様」に近い形で、 自然言語を併記しながらテストコードを記述する。 引用:https://ja.wikipedia.org/wiki/ビヘイビア駆動開発 #readyfor_meetup
Cypress で実践する BDD 実践にあたり採用したのが Cypress です。 Cypress は動作が軽快で BDD に適した
テストフレームワークです。 #readyfor_meetup
Cypress で実践する BDD Redux と Cypress は相性がよく、 Action dispatch で特定条件の再現が可能です。
こういった場面で、Redux の特性が活きてきます。 #readyfor_meetup
Cypress で実践する BDD 混み入った分岐条件でのみ現れる画面も、 どの「状態・Action」があれば再現できるのか? が、テストコードに落ちてきます。 #readyfor_meetup
Cypress で実践する BDD 特定制約時を再現するの事が容易なため、 テストファイルを細分化できます。 表示を即座に確認できるため、 ドキュメントとしても役立ちます。 #readyfor_meetup
None
Cypress で実践する BDD また、OpenAPI 定義によるMock サーバーを、 Cypress integration テストにも 活用しました。
#readyfor_meetup
Cypress で実践する BDD 「テストを書きやすい」環境は、 ライブラリ・ツール選択で明らかに 差が出てきます。 #readyfor_meetup
Cypress で実践する BDD また、ワークフローの工夫も大切です。 タスク分解の段階で「書きやすさ」は変わります。 タスクを細分化し、十分小さくすることです。 #readyfor_meetup
Cypress で実践する BDD チケットを発行し、チケット番号とともに 要求仕様の「空テスト」をコミット。 describe("「支払い方法」そのものが表示されない条件 ", () =>
{ xit("最終確認ページから「リターンを変更する」ために戻ってきた場合 ", () => { // TODO: #567 }); });
Cypress で実践する BDD PR とともに実装内容がテストに記されているため、 PR 概要を詳に書かずとも概要が伝わる状態が理想です。 describe("「支払い方法」そのものが表示されない条件 ",
() => { - xit("最終確認ページから「リターンを変更する」ために戻ってきた場合 ", () => { + it("最終確認ページから「リターンを変更する」ために戻ってきた場合 ", () => { }); });
Cypress で実践する BDD ライブラリ側もテストツール群も、 得意・不得意(オーバースペック)があります。 ライブラリ選定の際には「テスト観点」も含め、 バランスをとりながら選ぶ必要があります。 #readyfor_meetup
振り返りと 今後
制御・非制御 Component の I/F READYFOR Elements の再利用は とても上手くいきました。 しかし、一部検討余地がありました。
#readyfor_meetup
制御・非制御 Component の I/F たとえば、非制御 Component + Form 前提の props
設計が紛れていた事。 Form 都合の props を剥がすリファクタリングに 想定以上の工数がかかりました。 #readyfor_meetup
制御・非制御 Component の I/F また、制御 Component と比べると、 非制御 Component は
Redux と 相性がよくありません。 #readyfor_meetup
制御・非制御 Component の I/F React on Rails で利用していた箇所としては、 非制御 Component
がベストだった背景がそこに。 移行に必要なコストに違いないものです。 #readyfor_meetup
制御・非制御 Component の I/F READYFOR Elements の様な横断的な デザインシステムを構築するのなら、 制御・非制御 Component
を選択できる様な I/F を初期設計から盛り込むべきです。 #readyfor_meetup
これからも Redux を使いつづけるか? useContextSelector など、 Redux(useSelector) の代替となる様な React 公式 API
の検討も始まっており、 状態管理ライブラリ選定はやはり悩みどころです。 #readyfor_meetup
これからも Redux を使いつづけるか? これからも Redux を使いつづけるか? というと「都度検討」だと思います。 readyfor は機能単位で Next.js
を分割しているため、 状態管理も機能要件にあわせて選択できます。 #readyfor_meetup
これからも Redux を使いつづけるか? Redux のテスト優位性をあげたとおり、 フロントに複雑な表示ロジックを置く場合は、 導入メリットが多いです。 #readyfor_meetup
これからも Redux を使いつづけるか? 表示ロジックがフロントに寄る場合は採用、 表示ロジックがサーバーに寄る場合は不採用、 という切り分けをすると思います。 #readyfor_meetup
READYFOR の フロントエンドの分離戦略は スタートを切ったばかりです。 #readyfor_meetup
またいつか、 この続きを共有できる事を 楽しみにしています。 #readyfor_meetup
READYFOR x Next.js ご清聴ありがとうございました!