スタートアップにおけるフロントエンド開発を効率化するための環境整備
はじめに
株式会社MamaWell でエンジニアのお手伝いをしている、kkb0318 です。
プロジェクト立ち上げに携わり、効率的なUI開発に取り組みましたのでその内容をご紹介します。
立ち上げ時は以下のような状況でした。
- システムエンジニアは1人(フルタイムではない)
- チームにデザイナーもいるが画面デザインは未作成
- 開発期間は 3 ヶ月(それ以降も機能拡張は続く)
- リモート開発かつフルタイムではないため、チームでの会議の場が頻繁にとれない
期間的にも人員的にもなかなか厳しい状況です。
しかし、リソースが少ないからといって短期的な効率を求めてしまうと、負債が蓄積され中長期的な開発効率が著しく下がる危険性があります。
例えば、とりあえず動くものを作るという考えが先行しプロダクト開発のみに注力してしまい、CI/CD の仕組みすら整備されていなければ、継続的に作業コストが発生し非効率になってしまいます。(CI/CD 以外にも、自動テストやアーキテクチャの検討等、初期段階で技術的負債を積まない&効率化するような工夫が必要です。)
そのため、効率的に開発を進め、フィードバックを得られるような環境を開発初期段階で整えられることはとても重要です。
とはいえリソースが少ないこともあり、より効果的な施策に絞って実施する必要があります。
そこで私たちは、フロントエンド開発の効率化およびコミュニケーション不足の状況下でのフィードバックループに焦点を当て、効率的なフロントエンド開発への取り組みを実施しましたので、その内容をご紹介します。
フロントエンド開発を効率化する施策
概要
フロントエンド開発を効率化するために、GitHub Actions, Storybook, Chromatic を使用しました。
ソースコードは GitHub で管理し、GitHub Actions で CI/CD を回しています。
ブランチ戦略とCI/CDのしくみはざっくり以下のとおりです。
feature/xxx -> develop -> main
- main
- 動作保証された本番用コードが入ったブランチ。
- develop
- とりあえず動作するコードが入ったブランチ。
- feature/xxx
- タスクに紐づく、開発中のコードが入ったブランチ。
develop ブランチにマージされたタイミングで Chromatic へ UI を公開するように設定しています。(設定の詳細は後述)
これにより、本番環境へデプロイせずともタスク完了の都度デザインレビューを行うことができるようになります。
(開発スピードやコストとの兼ね合いから、今回はステージング環境を作りませんでした。)
Storybook の導入
本プロジェクトではフロントエンドフレームワークにReactを用いていますので、その前提での設定方法になります。
もし一からプロジェクトを作成したい場合、公式でも紹介されている以下のコマンドで作成するのが一番手っ取り早いです。
# See https://storybook.js.org/tutorials/intro-to-storybook/react/ja/get-started/
npx degit chromaui/intro-storybook-react-template taskbox
既存のプロジェクトにStorybookを導入するためには、次のコマンドでOKです。(自動的にフレームワークも認識してくれます。)
npx storybook init --builder vite
今回はビルドツールにviteを使用していたため、--builder
オプションをつけています。
オプションをつけず、後からvite用の設定をする方法は、Storybook公式サイトに記載されています。
ちなみに 上述のinit コマンドを実行すると、次のようにStorybookが提供するeslintPluginを導入するか聞かれます。
? Do you want to run the 'eslintPlugin' migration on your project?
私は自分用のlinter設定を優先して使いたかったので、Noにしました。
これで yarn storybook
コマンドを打つと、Storybookの画面が表示されます。
図はボタンコンポーネントの表示例です。
また、画面下部にはコンポーネントに渡すプロパティの設定項目があり、Storybookの画面からプロパティを変えることができるようになっています。
これにより、様々なプロパティでのコンポーネントのデザインを確認することができます。
このあたりのパラメータ設定は、.stories.tsx
ファイルに記載されていますので、自由に変更可能です。
以上でStorybookを導入できました。
Storybook を使用していなかったときは、コンポーネントの動きを確認するために、出来上がった画面にとりあえずコンポーネントを配置してデザインを確認し、微調整しながら開発していたため面倒でした。
Storybook を使うことで、画面を完成させるまえにコンポーネント単位のデザインを様々なパターンで確認しながら進めることができるようになったため、とても開発体験がよくなったと実感しています。
Chromatic でのUI公開
先述のとおり、チーム会議の時間をとりづらい状況であるため、フィードバックの機会が少ないことが問題となっていました。
そこで、開発中のUIを公開し、常時フィードバックを得られるような仕組みを作るためにChromaticを導入しました。
Chromaticの導入は、Storybookの設定が完了していれば非常に簡単です。
詳細な手順は公式の手順で確認いただくのが良いと思います。
ブラウザでStorybookの画面を確認できるだけでなく、前回ビルドとの差分を確認することもできます。
例えば以下の図は、Headerコンポーネントを変えた場合の差分のサマリー画面です。
Headerだけでなく上位コンポーネントであるPageにも変更が入っていることがわかります。
また、各コンポーネントの画面をみると、変更箇所がイメージおよびコードで比較してわかるようになっています。
これにより、想定外の変更があれば簡単に検知できますし、チームメンバーによるデザインレビューも捗りました。
このように、開発者にとっても非常に大きなメリットのあるツールであるため、Storybookを導入されているプロジェクトにはぜひおすすめしたいです。
CI/CD の導入
今回はGitHub Actionsを用いてChromaticへのUI公開および本番環境への自動デプロイを実装しました。
本番環境へのデプロイについては、今回のテーマではないので割愛します。
ここでは既にChromaticの登録が完了している前提で説明します。
Chromatic未登録の方は、公式サイトなどを参考に設定してください。とりあえずSignUpしてtokenが生成されていればOKです。
まずはGitHub ActionsのSecretにChromaticのtokenを登録します。
GitHubリポジトリのSettings -> Secrets -> Actions -> New repository secret から登録できます。
Secretの名前は任意です。(今回はCHROMATIC_PROJECT_TOKENという名前にしています。)
次にGitHub Actionsの設定ファイルを作成します。
設定は以下のとおりです。
# .github/workflows/chromatic.yml
name: 'Chromatic'
on:
push:
branches:
- develop
jobs:
chromatic-deployment:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install dependencies
run: yarn
# working-directory: ./ui/
- name: Publish to Chromatic
uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
# workingDir: ./ui/
ここで、Chromaticで公開したいプロジェクトのフォルダがホームディレクトリにない場合は、working directoryを設定する必要がありますので注意してください。
これでdevelopブランチへのマージをトリガーとしてChromaticへ公開できるようになりました。
さいごに
本プロジェクトは、執筆時点(2023/1)では現在進行形で進んでいます。
開発環境を先に作ったことで、とても快適に開発できています。
(そしてなにより開発がたのしい。。!)
まだ開発途中ですが、ある程度完成してきたらより詳細なフロントエンド開発のノウハウ・バックエンド・インフラについても記事にしていきたいと思います。
エンジニア募集
株式会社MamaWell ではエンジニアを募集しています。
勤務形態はリモートで、働く曜日や日時は自由です。副業・アルバイトも募集中です。
モダンなフロントエンド開発に興味がある方、新規プロダクト立ち上げに興味のある方はぜひ、以下までご連絡ください!
Discussion