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
850
App Router への移行は「改善」となり得るのか?/ Can migration to App Router be an improvement
takefumiyoshii
8
3.1k
フロントエンドの書くべきだったテスト、書かなくてよかったテスト
takefumiyoshii
39
15k
Webフロントエンドのための実践「テスト」手法 CodeZine Night #1
takefumiyoshii
24
8.4k
Next.js でリアーキテクトした話 / story-of-re-architect-with-nextjs
takefumiyoshii
12
8.7k
より速い WEB を目指す Next.js / nextjs-make-the-web-faster
takefumiyoshii
54
20k
Redux の利点を振り返る
takefumiyoshii
26
8.6k
Type-only Migrate by AST
takefumiyoshii
1
630
- Regular expression & Type - Naming Rule Linter
takefumiyoshii
1
370
Other Decks in Technology
See All in Technology
初心者向けAWS Securityの勉強会mini Security-JAWSを9ヶ月ぐらい実施してきての近況
cmusudakeisuke
0
120
Evangelismo técnico: ¿qué, cómo y por qué?
trishagee
0
360
いざ、BSC討伐の旅
nikinusu
2
780
オープンソースAIとは何か? --「オープンソースAIの定義 v1.0」詳細解説
shujisado
9
940
Python(PYNQ)がテーマのAMD主催のFPGAコンテストに参加してきた
iotengineer22
0
480
Adopting Jetpack Compose in Your Existing Project - GDG DevFest Bangkok 2024
akexorcist
0
110
TanStack Routerに移行するのかい しないのかい、どっちなんだい! / Are you going to migrate to TanStack Router or not? Which one is it?
kaminashi
0
590
Terraform CI/CD パイプラインにおける AWS CodeCommit の代替手段
hiyanger
1
240
ISUCONに強くなるかもしれない日々の過ごしかた/Findy ISUCON 2024-11-14
fujiwara3
8
870
Shopifyアプリ開発における Shopifyの機能活用
sonatard
4
250
OCI 運用監視サービス 概要
oracle4engineer
PRO
0
4.8k
IBC 2024 動画技術関連レポート / IBC 2024 Report
cyberagentdevelopers
PRO
0
110
Featured
See All Featured
Git: the NoSQL Database
bkeepers
PRO
427
64k
Building Better People: How to give real-time feedback that sticks.
wjessup
364
19k
Building Your Own Lightsaber
phodgson
103
6.1k
Code Review Best Practice
trishagee
64
17k
Why Our Code Smells
bkeepers
PRO
334
57k
We Have a Design System, Now What?
morganepeng
50
7.2k
Docker and Python
trallard
40
3.1k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Facilitating Awesome Meetings
lara
50
6.1k
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
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 ご清聴ありがとうございました!