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
1.1k
App Router への移行は「改善」となり得るのか?/ Can migration to App Router be an improvement
takefumiyoshii
8
3.6k
フロントエンドの書くべきだったテスト、書かなくてよかったテスト
takefumiyoshii
39
16k
Webフロントエンドのための実践「テスト」手法 CodeZine Night #1
takefumiyoshii
24
9k
Next.js でリアーキテクトした話 / story-of-re-architect-with-nextjs
takefumiyoshii
12
8.9k
より速い WEB を目指す Next.js / nextjs-make-the-web-faster
takefumiyoshii
54
20k
Redux の利点を振り返る
takefumiyoshii
26
8.9k
Type-only Migrate by AST
takefumiyoshii
1
700
- Regular expression & Type - Naming Rule Linter
takefumiyoshii
1
460
Other Decks in Technology
See All in Technology
増え続ける脆弱性に立ち向かう: 事前対策と優先度づけによる 持続可能な脆弱性管理 / Confronting the Rise of Vulnerabilities: Sustainable Management Through Proactive Measures and Prioritization
nttcom
1
210
クマ×共生 HACKATHON - 熊対策を『特別な行動」から「生活の一部」に -
pharaohkj
0
170
Webの技術とガジェットで那須の子ども達にワクワクを! / IoTLT_20250720
you
PRO
0
130
ファインディにおける Dataform ブランチ戦略
hiracky16
0
210
OpenTelemetry の Log を使いこなそう
biwashi
5
1.1k
経験がないことを言い訳にしない、 AI時代の他領域への染み出し方
parayama0625
0
250
From Live Coding to Vibe Coding with Firebase Studio
firebasethailand
1
290
大規模組織にAIエージェントを迅速に導入するためのセキュリティの勘所 / AI agents for large-scale organizations
i35_267
6
320
【CEDEC2025】LLMを活用したゲーム開発支援と、生成AIの利活用を進める組織的な取り組み
cygames
PRO
1
1.5k
興味の胞子を育て 業務と技術に広がる”きのこ力”
fumiyasac0921
0
280
メモ整理が苦手な者による頑張らないObsidian活用術
optim
0
150
公開初日に個人環境で試した Gemini CLI 体験記など / Gemini CLI実験レポート
you
PRO
3
570
Featured
See All Featured
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
Docker and Python
trallard
45
3.5k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.5k
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.7k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building Adaptive Systems
keathley
43
2.7k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.6k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
720
Thoughts on Productivity
jonyablonski
69
4.8k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.9k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
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 ご清聴ありがとうございました!