2021-7-16

個人開発の振り返り(フロントエンド編)

雑な技術メモ

個人開発で React+Firebase でそこそこの規模のものを作ったので振り返りをする。

  • React 全般
  • AtomicDesign
  • TailwindCSS
  • Zod
  • その他

React 全般

戻るボタンでのスクロール位置記憶が面倒

ReactRouter は戻るボタンによるスクロール位置の記憶を特にやっていなくて、History.scrollRestorationに任せっきり。

で、この API は当然といえば当然だけど「戻るボタン押して前画面を表示した後に表示内容のデータを通信で取得し表示する」みたいなケースには対応できない。API が「1000 までスクロールしたい」と思ってもコンテンツが空なのでその位置にスクロールできないので当然。戻るボタンを押して前画面が表示された時点で、データが表示されている必要がある。

今回は、この対策として useSWR を使用した。useSWR 自体はいいライブラリだけど、問題点として~Service という形で通信処理をラッピングしているのだが、そことのバッティングが発生してしまったのが問題。(投稿一覧の取得処理が、PostsService と useSWR を使った処理、二箇所で同じ処理が重複してしまっている状態)

prod/dev/test 以外の環境が存在する場合は dotenv-cli で切り分ける

https://dev.classmethod.jp/articles/react-dotenv-cli/

ReactScript は development、production、test の三環境しかデフォで対応していないので。

フロントエンドに Repository って名前の層は基本的に作らないほうが良い

これは命名の問題なんだけど、通信の層を Repository って名前で作るケースがあるがあれはやめたほうが良いと思った。

というのも、Repository って本当に単純な(list/add/save とかで抽象化出来るレベルの)データストアの抽象化なんだけど、WebAPI は抽象化対象としては賢すぎると思った。WebAPI はデータの単純な取得・保存だけでなく、他の処理もやってたりするので。

で、書きながら思ったけど、単純なデータ保存・取得は Repository、処理のキックとかは Service にしてもいいのかなとかも思った。(ただそこまでカテゴリ分けしなくてもいいかもとも思う

index.html で環境によって出力を変える

https://github.com/facebook/create-react-app/issues/3112

EJS 記法が使えるみたい(マジか。マジだった

Atomic Design

正直な所、分けるメリットを感じられなかった。少なくとも molecules と organism は色々な所で言われている通り振り分けが難しすぎる。

とはいうものの、汎用コンポーネントと特化したコンポーネントの区分けくらいはしておきたい気持ちがある。

- components
  - presentational
    - general
    - specialized
  - headless

みたいな構造がいいかも

TailwindCSS

  • メリット
    • CSS ファイルが必要ないので、ファイルの行き来が格段に減る。これが実際体験するとかなり楽。
    • コンポーネントを分割する際に、見た目部分は HTML をまるごとゴソッと持っていくだけで分割できる。これもめちゃくちゃ楽。
  • デメリット
    • デザイントークンを予め定義しておく必要がある。これが出来る案件実際かなり少ないのでは…?
    • 提供されていないスタイル指定が必要になった際にどうしても style とかに指定とかしないといけない。

開発体験としてはとても良いが、実案件で使うにはデメリットの部分がネックとなり中々採用が難しい気がした。

用意されたクラスだけではやはり不足することが多い。特に、min-widthとか paddin-top: 100%とか、どうしても TailwindCSS のクラスだけでは不足する。JIT モードという選択肢もあるみたいだが、現在まだプレビューという状態で、実際に使ってみたら HMR が効かなかったり不便なところがあったのでまだ微妙。なので、実際使うとしたら Emotion とか他の物と組み合わせて使う必要が出てくる。

デザイナーと最初からデザイントークン等に関して詰めれる案件や、デザインを自分で自由にできる個人開発ならとてもいいんじゃないかなという所。そうでなければ、CSSModule でいいんじゃないかなという感じ。

font-feature-settings: paltを使うと、Windows で偉いことになる

system-ui で適用される Yu Gothic UI が、約物が変な詰まり方する。

Zod

今回 HTTP レスポンスの型に関してはバックエンドと型定義を共有して解決したので、使用したのは環境変数と LocalStorage のバリデーション。

正直かなりいい。環境変数に関しては、不足しているものがあればビルドタイミングでエラーにしてくれるし、LocalStorage に関しては、保存されているデータが壊れていたりした際の対策が簡単に入れることが出来る。

これはしばらく採用し続けようと思った。

注意として、現在 ver3 が出たところなんだけど、現状 ver3 はかなりバギーで不安定。落ち着くまでは ver2 を使ったほうが良いかも。

その他

href や src にユーザー入力が入る場合は XSS に注意

https://blog.dododori.com/create/program/url-xss/

例えば、プロフィールに Twitter とかのリンクをおけるとかあるとき、href にはユーザー入力が入ることになる。その時に javascript:~ ってやられるとはい XSS 完了。

なので、まずバックエンドでは URL の形式か否かをちゃんと確認すること。

ちなみに、 https://blog.dododori.com/create/program/url-escape/ に記述のあるような \"><script>alert('error');</script> に関しては、React だと HTML 特殊文字をエスケープしてくれるので大丈夫っぽい。

overflow-wrap: break-word は親が可変の場合は効かないので注意

https://w3g.jp/blog/confusing_word-break_word-wrap

基本的には overflow-wrap を使うのがベター(本当に単語を折り返さないとニッチもサッチもいかない状況のみ折り返すので)

…なはずなのだが、コンテンツに応じて柔軟に幅を変えるようなケースだと、「単語折り返さなくてもいけるやん!」って判断して折り返さずに突き抜けやがる。

これに関しては、日本語圏のサービスなら word-break: break-all にしてしまって、気になるところだけ個別対処の方が良さそうと思った。