駑馬十駕

見習いSREが書くなんちゃってNext.js

React

概要

フロントエンドをちゃんと履修したことがないエンジニアがNext.jsを0から書くとどうなるかというのがテーマ。一応自分なりになぜその技術選定(ライブラリ選定)にしたかやアーキテクチャ(というほどのものではないけど)についても書く予定です。 フロントエンドエンジニアの方からすると

なんだこの書き方は...

と眉を顰めるような文章やコードが多々出てくるかとは思いますが、温かい目で見守り、もしよければTwitterのDMでビシバシ忌憚なき意見を下さると幸いです。

Katsukiniwa

技術スタック

  • React
  • Next
  • TypeScript
  • Tailwind CSS
  • react-hook-form/yup
  • (Firebase Auth)
  • eslint/prettier/husky/lint-staged
  • MSW/jest/testing-library

思想

CSSは高いレベルのUI/UXがもとめられないのであれば、まずMaterai UIやBootstrapのようなコンポーネントがそのまま提供されているCSS FWを候補に入れる。ある程度カスタムが必要であればTailwind CSSを選定する。Webフロントエンドが本職でない人間がstyled-componentsのようなCSS in JSできっちりコンポーネントを組むことは難しいからである。自分は絶対できないのともし挑戦したところで負債にしかならないコンポーネントを量産する未来が視えていたのでクラス名を当てるだけでスタイルも一緒にあたってくれてなおかつそれなりにカスタマイズできるTailwind CSSを選定した。こちら自分でも選択が正しいのか自信が持てないのでいろいろな方の意見を聞きたいです。注意していただきたいのは 筆者(実装者)がWebフロントエンドの経験が浅い という点です。

フォームはreact-hook-form一択だった。流行ってるのとドキュメントをパッと見た感じ使い方も難しくなさそうだったので。バリデーションにはyupを使いました。たしか公式ドキュメントにyupも一緒に紹介されていた気がするので。最近だと他にもバリデーションのライブラリは出てきているのでそれを使ってもよいと思います。自分はそこまで追ってなかったのでyupにしました。特に困ってないです。

eslintはNext.js側で提供されている設定をそのまま使っています。prettierはどうしたか忘れました。最初から設定済みだったかもしれないし、ネットから拾ってきたものを使っているかもです。

テストはcypressやplayweightなどのブラウザテストは書かずせいぜいcustom hooksに対して書く程度です。

Tips

React.ComponentProps 型を積極的に使おう

コンポーネントは当然上記の方針で組みます。

<CustomButton text="更新する" type="button" onClick={handleClick} className="bg-dark text-white px-4 py-2" />

なんてのは書かないです。(かく言う自分も昔は書いていました。) 新しいpropsが生える度にコンポーネントのPropsを更新するのは非現実的ですし拡張性がないので。 注意したいのはpropsにClassNameを受け取る場合Tailwindでは同じ属性のclass名が当たった場合後から追加されたクラス名が優先して当たるわけではないという点です。 つまり

type Props = React.ComponentProps<'button'> const BaseButton = ({ className, onChange, onClick, type }: Props) => { return ( <button onClick={onClick} onChange={onChange} className={`justify-center p-2 bg-red-600 text-sm flex items-center ${className ?? ''}`} type={type} > {children} </button> ) }

というAtomsを作成したとしてこれを使って後からClass名を当ててスタイルを上書きしたいとします。

<BaseButton className="bg-black"> 更新する </BaseButton>

しかし、この場合BaseButtonですでに bg-red-600 が当たっているので呼び出し側のClassNameで bg-black を当ててもボタンの色は黒くなりません。そのためこういった上書きをする場合はclsxというライブラリを使う必要があります。

TailwindCSSの重複したクラス名を上書き出来るようにする