初めまして。
2020年末からジモティーでフロントエンドエンジニアとして開発している山口です。
今回はジモティーのフロントエンド事情について紹介します。
ジモティーフロントエンドの現状
現在のジモティーのフロントエンドはRailsのAction Viewを用いて
- jQuery で Javascript 周り(一部のページの一部の DOM に対して jQuery 代替として Vueも利用)
- Rails の decorator でフォーマットして Haml でマークアップ
- Sass でスタイル付け
といった構成になっています。
しかしサービスの規模が大きくなってきたこともあり、どのidやclassをどの jQuery コードが参照しているのか追いづらかったり、 似たスタイルを持つ似た名前のclassが乱立してしまいどれを利用すべきなのかの見通しがつかないなど、開発が辛くなってきているのが正直なところです。
Railsの開発チームはアプリ向けのAPIの作成やバックエンドの開発と並行してフロントエンド開発も行っているため、 辛さが出てきた現状が会社として求める開発スピードUPの足枷になってきています。
新規プロジェクトにてReact(NextJS)を利用
今月リリースした新規プロジェクト、自治体向けの電子申請・申請承認システム「LOCONET(ロコネット)」にて、弊社としては初めて React を利用した開発体制を敷きました。
バックエンドはジモティーに引き続きReilsを利用し、フロントエンドはバックエンドとは完全に分離してReact(NextJS)+Typescript で作成、さらにOpenAPIによる APIドキュメント整備とStorybook によるコンポーネントのドキュメント整備を行うことでバックエンド開発者やデザイナーとのコミュニケーションを取りやすい環境を構築しました。
技術負債との比較
前述した現在のジモティーの開発状況と比べると今回の開発体制では
- styled-compomentsを利用でスタイルのスコープを制限してスタイルの見通しが付きやすくなる
- contextの利用を避けてあえてpropによるバケツリレーを選択することでstateなど変数の変更が追いやすくやる
- Typescript によりコードがよりドキュメントとして理解しやすい形で残るようになったため、第三者がコードを追いやすくなる
- バックエンドと分離されることでアプリチームと似た分担で開発が可能になり、適材適所の分担で開発が行えるようになる
- デザイナーとパーツ単位で実装しているスタイルを見ながら密なコミュニケーションが取れるようになる
などのメリットを得ることができました。
代わりに
- Typescript 導入により、追加で工数が発生してしまう
- 保守していかなかればならないものが増えた(OpenAPI,StoryBook)
といったデメリットは発生しています。
Typescript導入において型管理以外に特に時間を要したのは次に紹介する2項目です。
外部ライブラリ利用時の型調査の時間
外部ライブラリ使用した際にライブラリ内に定義されている型の内容、利用方法の確認に時間を要しました。
特に初めて利用するライブラリの場合、javascript時の倍は時間がかかる感覚です。
直で呼び出す場合より子コンポーネントへライブラリの一部を受け渡しする必要があった場合など子コンポーネントのpropの定義に悩むことが多かったです。(大抵公式のドキュメントにその場合の型の定義方法が書いてないので直接ライブラリを追ってみるしかなかったです)
例) React Hook Formの場合 https://react-hook-form.com/jp/get-started/
const { register, handleSubmit, watch, formState: { errors } } = useForm<Inputs>()
useFormで呼び出してきた各種メソッドregister, handleSubmit, watch, errors をコンポーネントへ受け渡したい時、どのような型で待ち受けるべきかがドキュメントからはわからず、なるべくanyなどを使わず実装しようとすると最適解を見つけるのに時間がかりました。
型推論のための追加記述
頻出するわけではないですが、遭遇した場合に解決の時間を用意したのがこちら。
適切な型推論が行われるようにするために javascriptだけならそのままで要件を満たして動作するコードに対して - typescriptが型推論に対応しているメソッドに書き直す - 自前で型推論させる処理を追加する(javascriptの動作上は必要のないコード) という対応をする必要が発生しました。
例) filterを利用してarrayを整理しても方が絞り込まれない例
const x = [123, null] // 型推論結果 const x: (number | null)[] const y = x.filter(v => v !== null) console.log(y) // [123] // 型推論結果 const y: (number | null)[] // number[] にならない
このままではビルドが通らないので型ガードを駆使したりして型を絞り込む必要が出てきますがチームへのTSの知見が溜まっていないと解決まで時間がかかってしまいます。
...
しかしながら、 Typescript導入やOpenAPI、Storybookはある程度のコード規模が大きくなり、チームの人数が増えてきたときに効力を発揮する要素なので投資として受け入れるべきコストだと考えています。
VueとReactの違い
実は私はジモティージョイン前までVueをフロントエンド開発に利用していたため今回のプロジェクトが React に触れる初の機会でした。
そのため Vue 開発と比べた時の違いについてもいくつか感じることができましたので紹介します。
自由度が高く、良くするも悪くするも開発者次第なReact vs 形式がしっかりしており、とっつきやすいVue
Vue はコンポーネント内で何をどこに定義すべきかはっきりしているのに比べて、React はとにかく自由度が高いため、開発者がやりたいように柔軟な書き方ができる反面、選択肢が多いため、知見がない状態ではベストプラクティスを見出すのが難しいと感じました。
コンポーネントファイル内でstateやeventなどを定義する場所(Vueはdataやwatch,methodなど書き場所が固定されていて開発者でバラつかない)や、スタイルの定義方法は他のオープンソースの事例をいくつか参照してみましたがどれもバラバラで自分たちに合ったやり方を見出す必要がありました。
スタイル付けに関してはスコープをコンポーネント内に留めたいのと、なるべくcssそのままの形で記載ができることをとってstyped-componentをチョイスしましたが正直Vueの方がシンプルにcssそのまま埋め込め、sassなども導入しやすかったので扱いやすかった印象です。
Typescriptとの親和が進んでいるReact、やれることが多いNextJS
自分がしっかりTypescriptに触れていなかった原因でもあるのですが、どうしてもVueの方がTypescript導入が遅れているので、きれいに導入できるReactの方が今のところは軍配が上がるという印象でした。
また、NextJSの方がISRなどへの対応が進んでおり、よりサービスに適した形でビルド方法を検討することができる点も好印象でした。
今後のフロントエンド開発
今後ジモティー自体でも Reils の MVC モデルに乗っかって jQuery を利用している現環境をやめて、今回 LOCONET で作ったようなフロントを分離した開発体制へ移行していく予定です。
かなり機能が多いサービスになっているため、大掛かりなプロジェクトにはなりますが、移行後はより良いユーザー体験と開発スピードを実現できると思います。
ジモティーは今回の私のように未経験技術へ挑戦する機会を積極的に与えてくださり 新規技術への興味関心度合いも高く、エンジニアとして働くのが非常に面白い組織です。
今後もこのサイトではジモティーのフロントエンド事情についての記事を投稿予定ですのでご期待ください。
弊社では一緒にプロダクトを改善していただける仲間を探しています!
こちらでお気軽にお声がけください!