Figma + Amplify Studio でのフロントエンド構築の流れを整理する

## 概要

前から存在しているツールなので今更ではありますが、今回は Figma と Amplify Studio を使ってReactベースのWebページを構築してみました。どちらも初めて使うツールで、使う前の感覚としては2つのツールを利用すれば、いい感じにほぼコードを書くことなくWebページを作れるのではないかと思っていました。しかし、実際に使ってみると、ただ単純にツールを使うだけではなく、Figma側で何を作るのか、Amplify Studio側で何を作るのか、それぞれの役割を整理しながら進めるべきだったと感じました。そこで、今回はその流れを整理してみたいと思います。

### (はじめに)Figmaとは

Figmaは、WebデザインやUIデザインを行うためのツールです。

![figma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/70f9d103-e81e-5c94-4e27-8f7a65037f42.png)

画面のように、オブジェクトの配置、色や枠のデザイン、エフェクトの設定がマウス操作でできます。

### (はじめに)Amplify Studioとは

Amplify Studioは、AWSが提供するフロントエンド構築ツールです。コードを書かずにUIをバックエンドに接続するよう設定をすることができ、開発者はロジックの実装に専念できます。

![amplify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/2c4a5c10-bef0-f72b-0a10-4c1f616f777e.png)

Figmaで作成したデザインの確認、オブジェクトに設定するパラメータの設定が画面上で可能です。この画面上で設定した内容をもとに、Reactコードを生成することができます。

、、と書いたものの、これはあくまで理想的な話であり、実際には、少しクセのある部分もあったので、そこも含めて記載できればと思います。

## 想定読者

以下の3パターンの方を想定しています。

* とりあえずFigmaとAmplify Studioを使うと何が良いのか知りたい方
  * 「作ったもの」、「全体構成図」、「ざっくり構築手順」が参考になるかと思います。
  * また、「所感」にFigma+Amplify Studioで開発した際の個人的なメリット・デメリットも記載しました。
* FigmaとAmplify Studioを使って構築をしたい方
  * 上記に加えて、「詳細構築手順」をご参照ください。
* FigmaとAmplify Studioを使った構築時の注意点について知りたい方
  * 「Tips: つまづいたところ」が参考になるかと思います。

## 目次

* 作ったもの
* 全体構成図
* ざっくり構築手順
* 詳細構築手順
* Tips: つまづいたところ
* 所感
* まとめ

## 作ったもの

今回デモページとして以下の謎解きWebページを作成しました。

https://gokan-485f6.web.app/

マルチデバイスに対応した画面表示がされていない・キャッシュ機能がないなど、つくりこみは甘いです(あと謎解きもそこまで洗練されていないです)。画面上の各オブジェクトのデザインやオブジェクトの配置はほぼ全てFigmaで作成しており、いわゆるニューモーフィズムなUIデザインがほぼコードなしで作成されているということに注目いただけると良いかなと思います。

## 全体構成図

![figure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/ba3a1b3d-c6a5-d949-eef5-5da548485e50.png)

①Figma上でデザインを作成し、②Amplify StudioにFigmaデザインをインポートし、③Amplify StudioからReactコードを生成するという構成になります。

## ざっくり構築手順

ざっくりとした構築手順は以下の通りです。pointは私が個人的にこうすると一番整理がついて構築を進められるのではと思ったやり方です。

* Figmaでデザインを作成
  * 【point1】Figma上でAtomic Designを意識したデザインを作成しておく
* Amplify StudioでFigmaデザインをもとにReactコードを生成
* オブジェクトの配置・ロジックの実装
  * 【point2】page単位でオブジェクトを配置する

### Figmaでデザインを作成

まずはFigmaで画面上に表示するオブジェクトをデザインします。Figmaの画面上でポチポチ操作して作成していくので、PowerPointやKeynoteでスライドを作成するような感覚で作成ができました。

![button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/303f42f3-8df7-37d3-a50f-05d93e477df2.png)

例えばボタンのオブジェクトを作成する場合は、◻︎のオブジェクトを作って、その背景色や枠線を変えるという作業イメージです。

### 【point1】Figma上でAtomic Designを意識したデザインを作成しておく

Figma上でデザインを作成する際に、Atomic Designを意識してデザインを作成しました。

#### Atomic Designとは

Atomic Designは、デザインを構成する要素を以下の5つの階層に分けて考えるデザイン手法です。
* Atoms
  * ボタン、テキストボックス、ラベルなど、最も小さな単位の要素
* Molecules
  * Atomsを組み合わせた要素。例えば、ボタンとテキストボックスを組み合わせたフォーム
* Organisms
  * Moleculesを組み合わせた要素。例えば、ページ全体のレイアウト
* Templates
  * ページ間での共通の要素。例えば、ヘッダーやフッター
* Pages
  * Templatesを組み合わせた要素。例えば、実際のWebページ

Atomの粒度からコーディングして実装という形が一般的かと思いますが、今回はあえて全ての工程をFigma上で行うことで、デザインとフロントエンドの実装を分業することができると考え、この方針をとりました。実際のFigmaの画面は以下です。

![atomic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/d1aee090-e1aa-19b8-9490-570ca0ca39e8.png)

Figmaで作成したデザインをどのようにReactに反映していくかは、後述のpoint2で説明します。

### Amplify StudioでFigmaデザインをもとにReactコードを生成

FigmaとAmplify Studioを連携させることで、Figmaで作成したデザインをインポートし、Reactコードを生成することができます。

まずAmplify StudioにFigmaのデザインをインポートします。

![component.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/7587209f-c71d-aaca-aec3-d8a7b1cf20e2.png)

Figmaで作成したデザインがAmplify Studio上では期待通りに反映されていないこともあるので、Figmaのデザインを修正、あるいはAmplify Studio上でデザインを修正します。特にFigmaをもとに生成したReactコードはAbsolute Positionで配置されており、さまざまなウィンドウの大きさに対応するなどのデザインにできていないことが多いので、Amplify Studio上で修正しました。

![configure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/be74294b-0841-c06e-3d9a-93c0aff1babd.png)

最後にReactコードを生成します。ui-componentsというディレクトリにReactコンポーネントが生成されます。

![ui-components.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/5f78cce8-a3a0-d62f-3ca9-df02da2e66ef.png)

### オブジェクトの配置・ロジックの実装

生成されたReactコンポーネントをもとに、オブジェクトの配置を行います。生成されたコンポーネントの使い方は、import文を追加した後に、タグを記載するだけです。

```js
import React from 'react';
import { AtomButton } from '../ui-components';

export const Test = () => {
    return (
        <>
            <AtomButton />
        </>
    );
}
export default Test;
```

![react-button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/1221af6c-2796-70fd-79bc-2c704e1864a5.png)

タグに追加で設定したいプロパティがある場合は、overridesというパラメータ値を追加して記述します。
    
```js
            <AtomButton
                overrides={{
                    "AtomButton": {
                      onClick: () => console.log('clicked'),
                    }
                }}
            />
```

例えばボタンのオブジェクトにOnClickイベントを追加する場合は、上記のようにoverrideにOnClickイベントを追加して、関数を別出しで作成して実装するイメージです。ロジック部分の記載方法は従来と変わりません。

このoverridesの記載が多くなると可視性が悪くなります。overridesの記載を少なくなる方法として、Amplify Studio上でパラメータをあらかじめ設定しておくことで、overridesの記載を減らすことができます。

![amplify-button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/e141c114-170f-ed88-6a6e-f813e39269ba.png)

上記のようにAmplify Studio上でパラメータを設定した場合、onClickの記載は以下のようになります。

```js
            <AtomButton
              onClickFunc={() => console.log("test")}
            />
```

用途が決まっているパラメータについては、Amplify Studio上で設定しておくことで、overridesの記載を減らすことができますが、逆にAmplify Studio上での設定となってしまうので、バージョン管理の観点で注意が必要かと思います。開発の際は何をAmplify Studio上で設定するか、何をoverridesで記載するかを整理しておくと良いかと思います。

### 【point2】page単位でオブジェクトを配置する

前節ではAtomのオブジェクトを配置するコードを記載しましたが、今回のデモページの開発では、page単位でオブジェクトを配置しました。

```js
import React from 'react';
import { PageProblem } from '../ui-components';

export const Test = () => {
    return (
        <>
            <PageProblem />
        </>
    );
}
export default Test;
```

上記のように実装すると、Figma上で作成したデザインがそのまま反映されます(もちろん見た目だけなので、クリックの挙動などは追加でコーディングする必要があります)。

![page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/b0d61021-1a81-98a1-f1b4-381d79c5b0ee.png)

このようにした理由としては、Figma上で作成したデザインをもとに、ページ全体のレイアウトを整理することができるからです。Atomから配置していくと、再度Moleculeから配置をコーディングする必要があるため、Figmaで作成したレイアウトをもとに生成されたコードからの恩恵が少ないと感じたためです。ただしこのやり方にはデメリットもあって、前節で述べたoverridesの記載が膨大になることがあります。大規模なオブジェクトの配置で、かつロジックの記載が多くoverridesへの記載が多くなる場合は、Atomは自動生成されたコードを利用し、Molecule以降は従来通りコーディングして配置するというのも一つの手かと思います。

## 詳細構築手順

### Amplify StudioとFigmaを連携する

#### Amplify Studioアプリケーションを起動する

* [AMSのコンソールのAmplify](https://ap-northeast-1.console.aws.amazon.com/amplify/home?region=ap-northeast-1#/)よりAmplify Studioの`使用を開始する`をクリックします。任意のアプリケーション名を入力し、`Confirm deployment`をクリックします。
* 数分待つとセットアップが完了します。`Backend environments`タブの`Studioを起動する`をクリックすると、Amplify Studioを起動できます。

#### Figmaを連携する

* Amplify Studioの左のサイドメニューから`UI Library`をクリックします。遷移した画面上でFigmaのデザインと同期することができます。
* 右上の`Sync with Figma`をクリックします。`Use our Figma plugin`をクリックすると、`AWS Amplify UI Kit`というプラグインが表示されるので、`Opne in Figma`でFigma画面を開きます。
  * この方式でFigmaページを作成すると、`My Components`ページ上にデフォルトのComponentが数十個存在しており、このままAmplify Studioと同期すると、必要ないComponentも同期されてしまうので、デフォルトのComponentを使用しないのであれば、`My Components`ページをあらかじめ削除するのが良いかと思います。
* Figma上でデザインを作成します。
  * デザインをAmplify Studioに同期させるためには、作成したオブジェクトに対し`Create Component`をクリックしてComponent化する必要があります。

![create-component.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420547/40763365-5d56-7a5c-e7c3-54adf174464c.png)

* 右上の`Share`をクリックすると、Link用のURLが表示されるので、それをコピーします。
* Amplify Studioのページに戻り、`Paste your Figma link`にコピーしたURLを貼り付けます。`Continue`をクリックすると同期が始まります。更新される内容のプレビュー画面が表示されますので、`Accept`をクリックします。同期が完了したら、Figmaで作成したデザインがAmplify Studio上に反映されることを確認してください。
* 以降、Figma上でデザインを修正すると、Amplify Studio上で`Sync with Figma`をクリックすることで、修正内容が反映されます。

### Amplify Studioでコンポーネントの設定を実施

Webページ上の表示方法や必要なパラメータ(ex. OnClickイベント)がある場合は、Amplify Studio上で設定します。
UI Libraryのページ上で、設定したいコンポーネントを選択し、`Configure`をクリックします。`Component Properties`の`Add prop`をクリックすると、パラメータを追加できます(パラメータ名・type(String,Numberなど)・default値が設定できます)。設定した内容は自動保存されます。

### Reactコードを生成

#### Amplify CLIをインストールする

* VSCode上のターミナルでnpmを利用してAmplify CLIをインストールします。

```sh
npm install -g @aws-amplify/cli
```

* AWSアカウントとの紐付けを実施します。ブラウザが開くので、AWSアカウントにログインします。リージョンの選択が求められるので、任意のリージョンを選択します。

```sh
amplify configure
```

* リージョン選択後、IAMユーザの作成を求められます。AWSコンソール上でIAMユーザを作成します。必要なポリシーは`AdministratorAccess-Amplify`です。作成したIAMユーザでアクセスキーとシークレットキーを作成します。VSCodeのターミナルに戻り、作成したアクセスキーとシークレットキーを入力します。
* 最後にprofile名の入力を求められますが、任意の名前を入力します。

#### Reactプロジェクトを作成する

Reactプロジェクトを作成します。特別な設定は必要ありません。

```sh
npx create-react-app [任意のプロジェクト名]
cd [任意のプロジェクト名]
# ローカルでreactプロジェクトを起動
npm run start
```

#### Amplify Studioで生成されたコンポーネントを配置する

* Amplify Studioで生成されたコンポーネントを使用するためのパッケージをインストールします。

```sh
npm install @aws-amplify/ui-react
```

* Amplify Studioのコンポーネントを取得します。Amplify Studioの任意のコンポーネントの詳細画面を開くと、画面下部に`Get component code`というボタンがあるので、それをクリックすると、コンポーネントを取得するためのコマンドが表示されます。それをコピーして、VSCodeのターミナルで実行します。以下のようなコマンドになります。

```sh
amplify pull --appId [Amplify StudioのアプリケーションID] --envName [Amplify Studioの環境名]
```

* 初めて上記のコマンドを実行した際は、アプリケーションの設定の入力が求められるので、以下のように入力します。

```sh
? Choose your default editor: > Visual Studio Code
? Choose the type of app that your building > javascript
? What javascript framework are you using > react
? Source Directory Path: >  src
? Distribution Directory Path: > build
? Build Command: >  npm run build
? Start Command: > npm run start
? Do you plan on modifying this backend? > Yes
```

* コマンドの実行が完了すると、`src`ディレクトリに`ui-components`ディレクトリが生成されます。このディレクトリにAmplify Studioで生成されたコンポーネントが配置されています。
* 以降、Amplify Studio上で何かしらの変更があり同期をしたい場合は、再度`amplify pull`コマンドを実行することで、ローカルのコンポーネントを最新の状態に更新することができます。

#### ui-componentsディレクトリのコンポーネントを配置する

* コンポーネントを配置方法は、ui-components上の対象のコンポーネントをimportして、対象のコンポーネントのタグを記入するのみです。例えば、app.jsに`AtomButton`を配置する場合は以下のように記述します。

```js
import React from 'react';
import logo from './logo.svg';
import "./App.css";
import { AtomButton } from '../ui-components';

function App() {
    return (
        <>
            <AtomButton />
        </>
    );
}
export default App;
```

#### Amplify Studio上で設定したパラメータを利用する

* Amplify Studio上で設定したパラメータを利用する場合は、Amplify Studio上で設定したパラメータ名をpropsとして渡します。例えば、ボタンのオブジェクトにあらかじめ設定したOnClickイベントを設定するための`onClickFunc`の値を追加する場合は、以下のように記述します。

```js
            <AtomButton
              onClickFunc={() => console.log("clicked")}
            />
```

#### Amplify Studio上で設定していないパラメータを設定する

* Amplify Studio上で設定していないパラメータを設定する場合は、overridesというパラメータを追加して記述します。例えば、ボタンのオブジェクトにOnClickイベントを追加する場合は、以下のように記述します。

```js
            <AtomButton
                overrides={{
                    "AtomButton": {
                      onClick: () => console.log('clicked'),
                    }
                }}
            />
```

### (省略)Webページのデプロイ

デモページはコストの兼ね合いでFirebase Hostingを利用してデプロイしましたが、今回の主題と関係ない内容のため方法は省略します。Amplifyを利用してhostingすることもできますが、こちらはコストがかかります。

## Tips: つまづいたところ

### Amplify Studio上での親子関係のコンポーネントの設定をする際、親コンポーネントの設定画面から子コンポーネントの設定ができない

FigmaでAtomオブジェクトを作成しコンポーネント化した後に、そのコンポーネントを利用してMoleculeオブジェクトをデザインしたことを例えば想定します。
Amplify Studio上でMoleculeのコンポーネントを設定する際、Moleculeコンポーネントの設定画面からAtomコンポーネントの設定はできませんでした。子コンポーネントの設定画面に移動して設定する必要があります。
一方で、子コンポーネントで設定した内容が親コンポーネントにReactのコードでは反映されてはいます。生成されたコードをみると分かりますが、Amplify Studioのコンポーネントごとにファイルが生成されそれぞれexportされており、親コンポーネントで子コンポーネントをimportしている形になっています。そのため、Figmaで作成した親子関係が全く反映されない、ということはありません。

### Figmaで作成したアニメーションはAmplify Studio上で反映されなかった

FigmaにはInteractive Designという機能があり、例えばボタンをクリックした際のアニメーションを設定することができます。しかし、Amplify Studio上で生成されたコードにはそのアニメーションが反映されませんでした。そのため、アニメーションを実装するためには、コーディングで実装する必要があるかと思います(反映する方法をご存知の方は教えていただけますと幸いです)。

## 所感

Figma+Amplify Studioを使ってフロントエンドを構築してみることで、以下のメリット・デメリットがあると感じました。

* メリット
  * デザイン関連の面倒なコード実装を省略できる
    * 従来では例えばボタンのデザインを変更する場合、CSSを書き換えつつデザインの微調整を行っていました。Live Serverなどを使ってリアルタイムでコードの変更を画面に反映させるにしても、コードで微調整するのは面倒な作業でした。Figmaでデザインすることで視覚的にデザインの微調整も可能で、そのままReactのコードに反映することができるので、微調整の手間が省けたと感じました。
  * デザインの変更をコードに反映させやすい
    * Figmaでデザインを修正すると、Amplify Studio上で`Sync with Figma`をクリックすることで、修正内容が反映されます。デザインの修正をコードに反映させる際に、コードを修正する必要がないのはメリットとして大きいと感じました。
  * デザインとフロントエンドの実装を(ある程度)分業できる
    * Webページをチーム開発する場合を考えた際、少なくともデザイナーとフロントエンジニアがいると思いますが、デザイナーが作成したデザインとフロントエンジニアが実装するコードをどう擦り合わせるかが課題だと思います。デザインをFigmaで作成し、その成果物のままAmplify StudioにインプットしReactコードとして生成できるため、従来のデザインとフロントエンドのグレーゾーンな箇所を減らすことができるのではと思いました。一方で、それぞれのコンポーネントの役割を加味してどのようなデザインにするか、パラメータ設定をどうするかついては、デザイナー、フロントエンジニア間のコミュニケーションが必要になるかと思います。
* デメリット
  * パラメータ設定が多くなると可読性が悪くなる
    * Componentに対してのパラメータ設定が多くなると、overridesの記載が膨大になることがあります。overridesの記載が多くなると可視性が悪くなるため、何をAmplify Studio上で設定するか、何をoverridesで記載するかを整理しておくと良いかと思います。
  * Figma+Amplify Studioで設定した内容のバージョン管理が難しい
    * ローコード開発の宿命かと思いますが、Figma+Amplify Studioで設定した内容は、バージョンとして明確に管理されていないので、もとのデザインに戻したいなどという場合に前バージョンへのリバートが難しいかと思います。ui-componentにコードを生成するたびにこまめにgit commitするなどの工夫を検討するのが良いかと思います。
  * Figmaでデザインした内容が全てAmplify Studioに反映できるわけではない
    * 「つまづいたところ」にも記載した通り、例えばアニメーションなどのデザインはFigmaで作成したデザインがそのままAmplify Studioに反映されるわけではないので、その辺りはコーディングでの実装が必要かと思います。
  * 生成したコードに関連する箇所で期待しない動作が発生した際、結局生成されたコードを見て原因を特定する必要がある
    * 生成されたコードに対して追加設定したパラメータが期待通り反映されていない際、生成されたコードがどういった構造になっているか実際のコードを見て確かめたことがデモページ作成時に何回かありました。コードが自動生成されるとはいっても、コードを読めばどういった挙動となるのか理解できる程度のReactの知見は持っておく必要があると思います。

開発で利用する場合は、事前にデメリットの部分をどのようにカバーするかということを検討する必要があると思います。

## まとめ

今回はFigmaとAmplify Studioを使ってフロントエンドを構築する体験を行った上で、実感と個人的に良さそうな実装の流れを整理してみました。Web画面の細かい実装がFigmaでのデザインで吸収できるのが個人的には一番大きなメリットに感じました。一方で、現状できなさそうなことや、やり方によっては可視性が悪くなることパターンもあると思いましたので、それらを事前に検討した上で利用することでより開発の効率化につながるのではと感じました。