💬

Chromaticを導入しました!

2022/12/17に公開

はじめに

半年くらい前にプロジェクトにStorybook及びChromaticを導入したのでその知見を今更まとめたいと思います。

Chromaticは開発者1人だけではなくエンジニアチーム全体、更にはデザイナーやPM/PdMみんなで使っていくことによってその効果が何倍にもなるツールです。Chromaticがどんなツールなのか、どうやって使うことができるのか、について書きたいと思います。

Chromaticとは何か?

ChromaticはStorybookをベースとしたUIテストツールです。Storybookのチームによって開発されており、フリーミアム型のサービスです。

簡単なイメージとしては、ローカルにあるStorybookをCDNにデプロイしたもの、みたいな感じです。


https://www.chromatic.com/docs/ より

デプロイすることで同じStorybookをチームみんなで見ることができるようになります。それに加えて、以下のことができます。

  • デプロイされたUIにChromatic上でコメント・レビューすることができる
  • UIがデグレてないか確認できる

Chromatic上でのコメント・レビュー

Chromatic上でUIを見ながらコメントができるので、コードベースではなくUIベースでレビューできます。開発した完成品をステージングに上げてそれをレビューしてもらう、という流れにしている方も多いと思います。Chromaticを導入することでステージングに上げることなくChromatic上でレビューすべて完結することができます。


UIに直接コメント

Storybookの開発チームが以下のブログで指摘しているように、フロントエンド開発の難点として、エンジニア・デザイナー・PM/PdMが1つの場に集まることができないことを挙げています。エンジニア同士がGitHub上でレビューし合ったりするように、プロダクトに関わる全員がChromatic上でUIに関してコミュニケーションを獲ることをできるのは強みなんじゃないかなと思います。

https://storybook.js.org/blog/how-storybook-helps-designers-developers-stay-in-sync/

デグレのチェック

あるコンポーネントのUIを変更したときに、意図していない変更が含まれていないか?、他のコンポーネントにも意図していない変更がされていないか?をChromaticは自動で見てくれます。開発の規模が大きくなってくるとコンポーネントの依存関係が複雑になってくることがあるので、そのような変更をキャッチしてくれるのは安心です。リファクタ行うときとかにも非常に有用なのでリファクタの心理的ハードルも下げてくれます。

下の図のように変更が合った部分を緑色で示してくれます。


https://www.chromatic.com/docs/test より

Chromaticの導入

用語の整理

ChromaticはローカルのStorybookをデプロイすることで「UI Test」と「UI Review」を行うことができるツールです。UI TestやUI Reviewを行うために理解する必要がある概念を整理しておきましょう。

Snapshotとは?

Snapshotはstoryの「画像」で、これを比較することで元にUI TestとUI Reviewを行います。

Chromaticは各storyをviewportごと・ブラウザごとにSnapshotを作成します。viewportやブラウザによってstoryの見た目は変わってくる可能性がありますが、それぞれでちゃんとSnapshotを作成してくれます。通常であれば、PC/Mobileでの見た目をチェックするため、その2つのviewportを設定しそれぞれでSnapshotを作成します。ブラウザに関して、無課金状態ではChromeでのSnapshotしか作成出来ません(課金するとIEやFirefoxでのSnapshotも作成できる)。

https://www.chromatic.com/docs/snapshots

UI Testとは?

UI Testは以前のSnapshotと今回のSnapshotの差分を検出するプロセスです。StorybookのコードをChromaticにデプロイする度に行われます。

このデプロイする(した)単位をBuildと呼びます。多くの場合、BuildはGitのコミットに紐づきますが、Gitのコミットは必ずしもBuildに紐づきません。

コードを変更するとUIが変わるのは当然ですが、大事なのは「意図していない変更が含まれていないか」をチェックすることです。UI Testをすることでそのチェックを簡単に行うことができ、安全にフロントエンド開発を行うことができます。

https://www.chromatic.com/docs/test

Baselineとは?

UI TestではSnapshotを比較すると述べましたが、ではどのSnapshotと比較するのでしょうか?必ずしも直前のBuildでのスナップショットと比較を行うわけではありません。Baselineのスナップショットと比較を行います。

Baselineは"the last known good state of story"と説明されています。これはどういうことでしょうか?ChromaticのUI Test・UI Reviewでは問題ない変更であればその変更を"Accept"します。そのAcceptされた=正しいUIだと認められたstory(good state of story)のうち、最新の(last known)ものをBaselineとして扱います。

逆に言うと、AcceptされていないものはBaselineとはなりません。加えて、Build間で(Snapshotに)変更がないstoryもそのままBaselineになります。つまり、ドキュメントの通り、Baselineになる条件は以下の2つです。

  • changed and those changes are accepted(スナップショットが変更されたが正しいものとしてApproveされる)
  • unchanged(Baselineのまま変更がなかった)

また、Baselineはブランチをまたいでも追跡されます。そのため、ブランチを切ったあとは元のブランチのBaselineが引き継がれます。

https://www.chromatic.com/docs/branching-and-baselines

UI Reviewとは?

UI Reviewは文字通り、UIをレビューするステップです。

UI Testは自動的に変更点を検出してくれますが、その変更が意図したものであるかは知る由もありません。UI Reviewのステップで、レビュアーが人間の目でUIをチェックしそれが正しいものであるか検証します。ChromaticではPull Requestと自動的に紐付けてくれ、UI Reviewが完了しなければmergeできない、みたいなことが出来ます(CIの設定)。

基本的には画像のようにチームメンバーを招待して、UI(のSnapshot)上に直接コメントし合い、レビューを行っていきます。Pull Request単位でさながらGitHubのようにレビューや修正の変遷を見ることが出来ます。


https://www.chromatic.com/docs/review より

https://www.chromatic.com/docs/review

Chromaticのセットアップ方法

※すでにプロジェクトにStorybookが導入されていることを前提としています。

まずはChromaticにSign upします。GitHubのアカウントでSign up出来ます。エンジニアでなくGitHubアカウントを持ってない場合でもメールアドレスで登録できます。

登録後、以下のような画面が出てくるかと思います。すでにプロジェクトをGitHubにあげている場合は、GitHubから対象のレポジトリを選びましょう。

これでプロジェクトとGitHubの連携が完了します。この際に<project-token>が発行されると思うので控えておきます。あとで使います。

ChromaticのSign upが完了したら、次はプロジェクトにChromaticパッケージをインストールします。

$ npm install --save-dev chromatic

これだけでセットアップは基本的に完了です。以下のコマンドを叩けばローカルのStorybookをChromaticにデプロイすることが出来ます。

$ npx chromatic --project-token <your-project-token>

package.jsonにもコマンドを入れておきましょう。以下のように追記すればnpm run chromaticを叩くとデプロイ出来ます。

"chromatic": "chromatic --project-token <your-project-token>"

しかし、多くのケースではプロジェクトトークンをそのままpackage.jsonに記載したくないでしょう。その場合はまず.envファイルに以下のようにプロジェクトトークンを書きます。

CHROMATIC_PROJECT_TOKEN=<your-project-token>

そしてpackage.jsonを以下のように書き換えればOKです!

"chromatic": "chromatic"

また、UI Reviewを行うためにサイドバーの設定(Manage)からUI Reviewを"enable"しましょう。これだけでPRとUI Reviewが自動的に紐付いてくれます。

https://www.chromatic.com/docs/setup

https://www.chromatic.com/docs/cli

開発の際に設定したこと

Storybookの開発と同様、Chromaticでも独自の設定を行っています。様々な設定に関してはドキュメントに譲るとして、自分が実際に行った設定について紹介したいと思います。

viewportの設定

先述したようにChromaticではviewportごとにSnapshotを作成します。このviewportは以下のようにstoryのparameterで設定します。各viewportを配列で与えます。

export default {
  title: 'components/atom/Button',
  component: Button,
  parameters: {
    chromatic: {
      viewports: [414, 1400],
    },
  },
} as ComponentMeta<typeof Button>;

ここで注意してほしいこととして、Storybook上のViewportとChromaticのViewportは異なります。上記のChromatic設定はあくまでもChromaticがSnapshotを作成するときに使うものなので、Storybookとは関係ありません。そのため、以下のように2つ設定することが多いです。

export default {
  title: 'components/atom/Button',
  component: Button,
  ...
  parameters: {
    viewport: {
      defaultViewport: 'iphonexr',
    },
    chromatic: {
      viewports: [414],
    },
  },
} as ComponentMeta<typeof Button>;

https://www.chromatic.com/docs/viewports

Snapshotを撮らないようにする設定

ChromaticはSnapshotの数に応じてお金がかかるため、できれば余分なSnapshotは作成したくありません。例えば動作確認を行うために作り、特に見た目をチェックしたい訳ではないstoryに関してはSnapshotは不要でしょう。

そのような場合はstory以下のように設定します。

export default {
  title: 'components/atom/Button',
  component: Button,
  parameters: {
    chromatic: {
      disableSnapshot: true,
    },
  },
} as ComponentMeta<typeof Button>;

https://www.chromatic.com/docs/ignoring-elements

設定がややこしかったところ

titleを変更したときの挙動

Chromaticはstoryのtitleを元にSnapshotを追跡しています。titleが同じであれば同じstoryとして認識し、UI Testを行ってくれます。

逆に言うとtitleが異なると内容が同じでも違うstoryとして認識してしまうので注意が必要です。一度titleを変更してデプロイしてしまうと後にtitleを元に戻してもそれは新しいSnapshotとして扱われます。

mergeしたときの挙動

ブランチをmergeするときBaselineが複数存在する可能性があります。その場合、最も新しくapproveされた方をBaselineとしてUI Testが行われます。

https://www.chromatic.com/docs/branching-and-baselines#merging

rebaseしたときの挙動

ChromaticのBuildはGitのコミットに紐づくため、rebaseしてしまうとめんどくさいことになります。rebaseはコミットをgit historyから消してしまうため、Baselineが含まれているコミットも消してしまう可能性があります。

この場合、Chromaticはそのブランチにおける最新のBuildをBaselineとします。もしそのBuildをBaselineとしたくない場合はデプロイする際に$chromatic --ignore-last-build-on-branch=<branch-name>を叩きます。消されたコミットもChromaticの「Builds」上には残り続けます。

https://www.chromatic.com/docs/branching-and-baselines#rebasing

Chromaticを使ってみて思ったこと

UI Testはフロントエンドの品質担保のためには絶対に必要なステップだと思います。ChromaticはUI Testを行うことの出来るツールの1つです。Storybookを導入しているプロジェクトであれば簡単に導入・テストを行うことが出来ます。

一方で、ある程度の大きさのプロジェクトになるとほぼ確実に課金が必要になります。月5000枚以上のSnapshotを取ると課金になりますが、小規模な個人開発で無い限り確実に超えると思います。しかも結構お高いので、気軽に導入出来るものではありません。調べてみると日本ではChromaticを使わずにこのようなUI Testシステムを自前で実装している会社もあるようです。Storycapとreg-suitを使うやり方が最もメジャーみたいです。どのツールを使うのかはROIを考えての判断になるでしょう。何れにせよUI Testが大事であることには変わりません。

https://engineer.crowdworks.jp/entry/vrt_with_regsuit

Chromaticのもう一つのメリットとしてUI Reviewがあります(これは他のツールでは無いChromaticならではの機能かもしれません)。UI Reviewの大きな強みとしてはエンジニア以外のメンバー、デザイナーやPMの方などが集まってUIを議論できる場を提供出来ることです。Storybook・Chromaticの開発チームはフロントエンド開発の難点として、「エンジニア」「デザイナー」「PM/PdM」が1つの場に集まることができないことを挙げています。今までSlackなどで散発的に行われていたレビューを一箇所にまとめることで、レビューも効率化出来るでしょう。しかし一方で、このレビュー方式をチームに浸透させていく必要があります。開発者以外のメンバーにChromaticを利用する意味を理解してもらったり、使い方をマスターしてもらったりするのは簡単なことではないでしょう。

開発者視点で言うと、Chromaticにデプロイした際にスナップショットがどのように撮られるのかを事前に知ることができない、実際にデプロイしてみるしかない、というのは設定をチューニングしていく際にかなり面倒でした。

GitHubで編集を提案

Discussion