はじめに こんにちはログラスのフロントエンドエンジニアの @Yuiiitoto です。 「次世代型経営管理クラウド」のSaaSを開発しています。
今回Reactを使って開発しているログラスのフロントエンドがどういう技術を使っているのか、なぜそれを選んだかについて解説していきます。
Reactはライブラリの数が豊富な反面で群雄割拠している領域が多く、技術選定がとても大変です。 同じ悩みを抱えるフロントエンドエンジニアの方に少しでも力になれればと思って記事にしました。
ログラスのフロントエンド 似たようなサービスの場合に特に参考にできる場合が多いと思うので、記事の前提としているサービスについて少し説明します。
ログラスはいわゆるtoBのSaaSの業務システムみたいな立ち位置です。 ほぼ全てのページに認証が入り、画面の中の要素はtoCのサイトより多めです。 Next.jsで構成されていて、SSGやSSRなどは使わずにデータはクライアントからフェッチしています。
※ログラスは事業の予実を管理するサービスです。
解説する領域 今回、技術選定する領域は以下の3つです。
状態管理 スタイリング フォーム 状態管理 状態管理はSWRとContextを使った状態管理をしています。 APIからの値はSWRで管理していて、それ以外の値はContextを使って管理しています。
他に考えた選択肢では以下が挙げられます。
Redux + Redux Toolkit + redux-thunk(or saga) Redux + Redux Toolkit(非同期はTooklit内の機能のAsync Thunk) Redux + CustomHook なぜSWR + Contextなのか アプリ内で状態管理したいものが大抵はAPIのデータ + SWRはそれに特化したライブラリだからです。 大抵のものがSWRで管理しているので、それ以外のものをReduxで管理するのは学習コストとしても見合わないとしてContextを使うという判断をしました。
また、Reduxを使う場合はアプリ内で中央集権的に管理せざるをえなくなるので、マイクロフロントエンドやコンポーネントライブラリの切り出しが将来的に難しくなると判断しました。 たとえばモーダル(ポップアップ)などの開閉状態をアプリ全体で保持したい場合、Reduxを使うと他のストアの情報と依存してしまいますが、Contextの場合は依存を最小限に抑えることが可能です。
SWRのメンテナンス性ですが、Vercel製で公式ドキュメント内でも使用が推奨されていることもあり、問題ないと判断しています(まだv0.xだけど)。
The team behind Next.js has created a React hook for data fetching called SWR. We highly recommend it if you’re fetching data on the client side. It handles caching, revalidation, focus tracking, refetching on interval, and more. And you can use it like so:
SWRの紹介として、以下の記事なども参考になります。
スタイリング 非常に悩ましい領域ですね。ここだけで一つの記事になりえます。 最終的にログラスが選んだのは emotion でした。
他に考えた選択肢は以下の4つです。
CSS Modules Styled Components Tailwind CSS linaria CSS ModulesはNext.js推奨?? まず物議をかもしているのがこちらのIssue。
We should update the page to be clear about the advantages of CSS Modules over css-in-js, mainly being that you don't need JS to add the CSS as CSS Modules are concatenated into many minified and code-split .css files. Ideally users should end up thinking that CSS Modules are the preferred solution, but any CSS-in-JS library is also an option. どうやら最適化の観点からNext.jsは今後CSS Modulesを推奨していくような流れを感じ取ることができます。 しかしまだOPEN状態なIssueなので確定というわけではないですが、CSS Modules→CSS-in-JSという流れだったものを見事に逆行させるIssueです。
国内での詳しい考察は以下の議論でも確認できます。
この一連の流れを見たときに、それでもなおログラスではCSS-Modulesを採用しませんでした。
CSS-Modulesの考えられるデメリットは以下のようなものがあげられます。
ファイル数が増える タイプセーフではなく、存在しないクラス名も当てられる。検知がエディター依存になる また最適化の観点からもログラスのフロントエンドはほぼすべてのページで認証がかかっておりSSG、SSRは採用していなく、またそこまでスピードを求められるサービスではないため観点として除外しました。
王道のStyled-Componentsか おそらく一番使用者が多いのはStyled-Componentsでしょう。 しかしこれは以下の理由で採用しませんでした。
Styled componentsを使うかcss propsを使うかで迷う Styled componentsなのか普通のコンポーネントなのか一見してわかりにくい Angular,Vueの人の学習コストが少し高い 特に3つ目のAngular Vueの人でも学習コストが高いというデメリットはログラスでは重要な観点の一つです。
最終的なEmotionのスタイル 最終的には以下のような書き方で落ち着きました。
const Todos = () => (
<ul css=styles.list>
<li css=styles.listItem>
aaa
</li>
<li css=styles.listItem>
bbb
</li>
<li css=styles.listItem>
ccc
</li>
</ul>
);
const styles = {
list: css`
display: flex;
`,
listItem: css`
margin-left: 8px;
&:first-of-type {
margin-left: 0;
}
`,
}
この書き方であれば生のCSSに近い感覚で書けるのでAngularやVueの方でも不自由なく書けそうだと判断しました。
フォーム
お次はフォームです。フォームは以下の3つの選択肢から考えました。
React Hook Form React Final Form Formik 最終的に選んだのは React Hook Formです 。 しかしこれは正直React Hook Form と React Final Formのどちらかであれば好みの問題だと思います。 Formikは明確にパフォーマンスの観点でデメリットがあるので使用はおすすめしません。
議論の参考としては Blitz作者のフォームの比較記事が参考になります。 日本語の要約記事はこちらです。
Formik 以前使ってたけど,パフォーマンスめっちゃ悪いって気づいたから,Formikは無しで。 React-final-form 最近ずっと使ってるけどいい感じ。 React-hook-form ほとんど使ったことない。 記事ではこう要約されています。
React Hook Formは初めからReact Hookをもとに設計されているので、 フォームのロジックなどをカスタムフックに切り出すことが容易にできます。 useControllerなどを使えばコンポーネントの分割も簡単に行えるので個人的には一番オススメできるライブラリです。
To Be Continued 今回は全体の技術選定ということで深くは解説はしませんでした。 もし今回触れた3領域で詳しい話が聞きたい場合はぜひご連絡ください。
また今回触れてなかった領域で以下が挙げられます。
これらもリクエストがあれば順次まとめていくのでもし興味があればご連絡くださいー!
We're hiring! ログラスはこの記事を見ているあなたのような好奇心旺盛なエンジニアを求めています。 興味があればぜひご応募ください!