バクラクビジネスカードの立ち上げで挑戦したフロントエンドの取り組み
LayerXでエンジニアをしている松本駿(toshi1127)です。 現在はバクラクビジネスカードとバクラク電子帳簿保存の開発に携わっています。 この記事はLayerX Tech Advent Calendar 2022の22日目の記事です。
バクラク事業部では、これまでフロントエンド開発にNuxt.js + TypeScriptを中心とした技術スタックでを採用してきました。 8月から提供させていただいているバクラクビジネスカードでは、React + TypeScriptを採用しました。 新たに挑戦したフロントエンドの取り組みを中心に、技術選定の背景や2〜3ヶ月という短期間でリリースするために意識したことを紹介できればと思います。
開発体制の特徴としては次のとおりです。
- バックエンド/フロントエンド関わらず、それぞれが機能単位で一気通貫で開発を行う
- Reactの採用実績がなく、経験者が少ない
- デザイナーがデザインとUIの修正を同時に行う
バクラクビジネスカードとは
現場の従業員が柔軟に利用できるのはもちろん、経理の方が使いやすく、管理もしやすい次世代の法人カードです。
バクラクビジネスカードの特徴は以下のとおりです。
- 用途ごとに何枚でも
- Web上で即時にカード発行可能
- 役員用・事業部用など用途別に使える
- Web上で即時に利用停止可能なため、安心して社員に渡せる
システム概要と技術構成
バクラクビジネスカードには、二つのフロントのアプリケーションが存在します。 お客様にご利用いただくアプリ(Web)と、社内の管理業務(与信, 入金処理など)を行うアプリ(Admin)の二つがあります。
技術構成
- React
- Typescript
- Apollo GraphQL
- Turborepo
- Vite
フロントエンド設計で取り入れたこと
1. Monorepoの採用
バクラクビジネスカードでは、FEでMonorepoを採用し、単一のリポジトリでお客様にご利用いただくアプリ(Web)と、社内の管理業務(与信, 入金処理など)を行うアプリ(Admin)を管理しています。
Monorepo とは
Monorepo とは一つのリポジトリに複数プロジェクトのコードを格納するリポジトリを指します。
Monorepoにした背景
以下の理由から Monorepo を採用しました。
- 仕様を理解していく中でコードの再利用できる部分が多いことがわかり、共有モジュールを楽に使用できることの恩恵を受けられそうだった。
- 既存のバクラクシリーズの開発や管理画面を開発するする中でメリットを感じる点があった
- リポジトリを跨いで同じコードを実装することがあり面倒
- ライブラリのバージョン管理が大変
- 標準化がしにくい(ESlintなど)
Monorepoには、Turborepoを使用しています。
ディレクトリ構成
apps と packages 2つのディレクトリがあります。 apps配下にお客様にご利用いただくアプリと、社内の管理業務(与信, 入金処理など)を行うアプリの二つがあります。 packages配下には、共通で利用できるUIコンポーネントやロジック、eslintのpackageがあります。
├── apps │ ├── admin │ └── web └── packages ├── eslint ├── ts-config └── ui ├── components ├── contexts └── hooks ※細かい部分省略
2. Reactの採用
以下の理由から React を採用しました。
- BootstrapVue の Vue 3 の対応状況の遅れ
- React の TypeScript(TSX)との親和性の高さ
既存プロダクトで Vue を採用しており、開発メンバーが慣れているという点では Vue に優位性がありました。 しかし、他プロダクトとの操作体験を揃えるため、Bootstrapを採用することは重要度高いものでしたが、Vue3の対応状況が進んでいない状態でした。
既存プロダクトを保守していく中でTypeScriptの恩恵を存分に受けたいケースが出てきた(不正な props を渡してしまいバグにつながる、vuex跨いだ時に型が効かないなど)のと、このタイミングでVue2で作るよりも会社としてReactの採用事例を作っておきたいといった理由からReactの採用に踏み切りました。
Viteの採用理由
バクラクビジネスカードでは、プロダクトの性質上、SSR/SSG/ISRする仕組みが不要だったため、Next.js / Remixなのどフレームワークは採用していません。 それを鑑みて、以下の理由から Vite を採用しました。
- create-react-appはフルメンテナが不在で、今後の保守に懸念があった
- Buildが早い
- SSR を必要としないシンプルな SPA を簡単に構築できる点
社内で初のReact採用にあたり生産性を出せるように意識したこと
従来の開発体験に近くしないと、他エンジニアやデザイナーメンバーの学習コストが上がりすぎでリリースが遅れてしまうリスクがありました。 (デザイナーの方が既存プロダクトのUI実装までされていた経験があったので、バクラクビジネスカードの開発も徐々にしていただけると良いなと考えていた) そのため、下記のことを意識していました。
- コンポーネントのスタイリングにはCSS Modulesを使用することで、開発体験を寄せて既存のSassの資産を流用できるようする
- デザイナーメンバーとのペアプロを実施し、Vueとの差分を説明しながら小さめの修正を一緒に対応する
- 先回りしてドメインに依存しないComponentを既存プロダクトと遜色ない程度に充実させることによって、プロダクト自体の開発に集中できる状態を作る
3. 設計にFragment Colocationを導入
Fragment Colocation とは、コンポーネントが必要とするデータを Fragment として定義してコンポーネントとco(一緒に) locate(配置する)する手法です。 既存のプロダクトでは、コンポーネントがどんなデータを必要としているかを、ページのクエリとして記述するという形を取っていました。そのため下記のような問題がありました。
- 各コンポーネントの知識をページがもつ必要があり、コンポーネントの追加や変更があった際、同時にページのクエリも変更しなければならない
- コンポーネントのPropsの型をGraphQLのModelの型にしていたため、Propsの不足に気づけない、必要以上にデータを取得してしまう
GraphQL はクライアントが自由にレスポンスの形式を指定できて便利なのですが、度重なる機能改修を重ねても上記のような状況が発生しにくいように、Fragment Colocation を採用しました。
import { gql } from '@apollo/client'; import { CardFragment } from './__generated__' const cardFragment = gql` fragment Card on card { name number } ` const Card = ({ card }: { card: CardFragment }) => { return ( <> <p>{card.name}</p> <p>{card.number}</p> </> ) }
結果として、「そのコンポーネントで必要なデータはなにか」を管理しやすくなることで、Fragment を元に生成した型を Props の型として使用することで変更に強くなり、under-fetching / over-fetching が抑制できるようになりました。
リリースしてみて
まず、Reactの採用がスケジュール影響や、既存プロダクトとのユーザー体験的な違和感につながることなく出せて非常によかったです。
リリースしてから約4ヶ月間、FEの不整合によるバグが発生していないですし、次新規プロダクト作るならReactかなという話も上がるようになりました。 バクラク事業部として良い採用実績が作れて良い挑戦になったかなと思います。
おわりに
この記事では、バクラクビジネスカードのフロントエンドについて、技術選定や設計の背景を紹介しました。 まだまだ面白い話があるので、興味ある方はカジュアル面談等でお待ちしております!
フロントエンドに関わるポジションとして以下を募集しています。
気になった方は是非チェックしてみてください!