AWS Amplify Studio を触ってみた
すこし前に話題になったAmplify Studioを触ってみました。
ReactもFigmaも詳しくないのですが、今っぽいサービスなのと実際にどのくらい使えそうかを確認する目的です。
主に3つツールがそれぞれの役割で登場することになります。
- Amplify Studio(AWSコンソール)
- データモデルの定義
- デザインの取り込み
- Figma(デザインツール)
- UIコンポーネントの作成
- ターミナル、VSCodeなど
- Amplify CLIから生成コードの取り込み
- Reactアプリケーションの開発作業
行う順序の縛りはそこまでないので、得意なものや気が向いたものから始められると思います。
※ 動作環境:macOS Monterey / npm v8.19.2 / Node.js v14.17.0
Amplify StudioでStudio起動
AWSコンソールからAmplifyに移動し、Amplify Studioの「使用を開始する」からスタート。
アプリケーション名は適当に「amplify-studio-sample」に。 2,3分でセットアップが完了する。
「Studioを起動する」をクリック。
Studioが起動される。
Figmaのデザインをインポート
Figmaのデザインを取り込む設定をする。
サイドバーの Design > UI Library を選択。「Get started」をクリック。
今回はFigmaのデザインをゼロから作るのではなくテンプレートを使う。
「①Use our Figma templateto get started」をクリック。
ブラウザでFigmaのページが開くので「コピーを取得する」をクリック。
Figmaにファイルがコピーされる。
右上の「共有」から「リンクをコピーする」をクリック。
先ほどのAmplify Studioのページに戻ってコピーしたリンクを②に貼り付け。
アップデート(初回の場合はすべての変更)を取り込むかどうかを聞かれる。
「Accept all changes」で取り込み。
以上でAmplify StudioとFigmaの連携が完了。
データモデルの作成
Set up > Data の「Add model」からデータモデルの追加を行う。
今回は書籍のタイトル、書影、金額を表示できるようなものにする。
編集が終わったら「Save and Deploy」をクリック。
データモデルのデプロイは5分ほどで完了。
Manage > Content のからサンプルデータを作成しておく。
データモデルとコンポーネントとの紐付け
次にコンポーネントとの紐付けをする。
UI Libraryから「TallCard」を選択して「Configure」をクリック。
「Component properties」で登録したデータモデルを選択。
「Child properties」では項目を紐付け設定する。
紐付けしていくと、先ほど登録していたサンプルデータのプレビューが見れる。
次にコレクション(作成したコンポーネントのかたまり)を作成する。
TallCardコンポーネントの作成画面から「Create collection」を選択し「TallCardCollection」の名前で登録。
今回は横並びのリストとしてレイアウトを決定してコレクションの作成を完了。
Amplify CLIのインストールとユーザー作成
Amplify CLIのインストールをする。
$ npm install -g @aws-amplify/cli
command not found: amplify で詰まったが、ターミナル再起動で次へ進めた。
AWSアカウント設定をする。
$ amplify configure
ブラウザが起動してログイン画面が表示される。
ブラウザでログイン後、ターミナルに戻ってエンターを押す。
Follow these steps to set up access to your AWS account: Sign in to your AWS administrator account: https://console.aws.amazon.com/ Press Enter to continue
リージョン選択、IAMユーザー名の設定をする。
Specify the AWS Region ? region: ap-northeast-1 Specify the username of the new IAM user: ? user name: amplify-xxxxx
ブラウザが起動してIAMユーザー作成画面が表示される。
デフォルトで権限選択されているので、そのままユーザー作成する。
ブラウザで作成後、ターミナルに戻ってエンターを押す。
Complete the user creation using the AWS console https://console.aws.amazon.com/iam/home?region=ap-northeast-1#/... Press Enter to continue
ターミナルで作成したIAMユーザーの accessKeyId と secretAccessKey を入力する。
Profile名は amplify-xxxxx
などに設定して完了。
Enter the access key of the newly created user: ? accessKeyId: ******************** ? secretAccessKey: **************************************** This would update/create the AWS Profile in your local machine ? Profile Name: amplify-xxxxx Successfully set up the new user.
ローカルでReactアプリの作成
必要なUIモジュールをインストールしておく。
$ npm i @aws-amplify/ui-react
Reactアプリの作成をする。
$ cd /[PATH]/amplify-studio-sample $ npx create-react-app .
y
ですすむ。
Need to install the following packages: create-react-app@5.0.1 Ok to proceed? (y)
アプリ作成完了。
Success! Created amplify-studio-sample at /[PATH]/amplify-studio-sample
$npm start
でReactアプリの作成できたことを確認。
ローカルのReactアプリで動作確認
Amplify Studioで作成したコンポーネントコレクションの「Get component code」をクリック。
初回は「Initial project setup」の内容を行う。
src/index.js の中身を下記に変更。
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import Amplify from 'aws-amplify'; import "@aws-amplify/ui-react/styles.css"; import { AmplifyProvider } from "@aws-amplify/ui-react"; import awsconfig from './aws-exports'; Amplify.configure(awsconfig); const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <AmplifyProvider> <App /> </AmplifyProvider> </React.StrictMode> ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
次に「Use this component」の内容を行う。
コンポーネントをローカルにプルする。
$ amplify pull --appId XXXXX --envName staging
ブラウザで認証を開いたりするがOKのまますすめる。
その後コマンドで質問受けるがこれも基本はそのまま。一部のコマンド設定を変更した。
... ? Choose your default editor: Visual Studio Code ? Choose the type of app that you're 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 start ...
src/App.js を下記に変更する。
import { TallCardCollection } from './ui-components'; function App() { return ( <div className="App"> <TallCardCollection /> </div> ); } export default App;
コマンドで $ npm start
とすると、ブラウザでAmplify Studioと同様のコンテンツが表示された。
その他
/src/ui-components/
配下にFigmaで作成したコンポーネントのコードが配置されている。
データモデルの型は /src/models/schema.js
に定義されている。
データはDynamoDBに格納されている。
まとめ
良さそうなこと
- デザインや開発の不得意がある人でもひとりで簡単な認証含めたサービスが作れてしまいそう
イマイチそうなこと
- Amplify Studioでコレクション作成する作業でビジュアルの再現ができなそう(他のやり方があるのかも?)
- Amplifyの生成コードとローカル(Git)のコードとごちゃごちゃになりそう
- どこまでFigmaのコンポーネントとするか、すべてをコンポーネントにするかなど、設計や認識合わせが事前により必要になってきそう
エンジニアとデザイナーが相互に理解があれば大きな問題にはならないかもですが、実際のプロジェクトのフローを想定すると、ここ誰がやるのかなみたいなフローがちょくちょくあったので、現実的に難しくなりそうな点もありました。
正直勝手に自分の期待値が高かっただけなのか、もう少しいい感じのサービスなのかなと想像してしまっていました。
ただ流行り系のサービスではあるので、アップデートは追っていこうかなと思いました。
CSS Container Queries を理解する
Container Queriesとは
MDNによると、「コンテナのサイズを見て、コンテナ内のスペースに応じてレイアウトを調整できる」とあります。
この「コンテナ」とは、基本的にスタイル指定を行うコンポーネントの親要素になります。
例えば、サイドバーとメインエリアで構成要素が同等のアイテムコンポーネントAがある場合、
のそれぞれが「コンテナ」に当たり、コンテナのサイズに応じてコンポーネントAのCSSの指定を書き分けることが可能 になります。
Container Queriesは現時点でFireFox以外のモダンブラウザでサポートされています。
FireFoxにも対応が必要な実際のプロジェクトでは、Polyfill を使用することが現実的な手法となりそうです。
Media Queriesとの違い
従来より使用しているMedia Queriesとの違いはどこにあるのでしょうか。
Media Queriesでは、基本的に画面のビューポート幅に応じてレイアウトを切り替えていました。
対してContainer Queriesは、コンテナ幅に基づいてコンポーネントのCSSを切り替えることができるため、これまでより柔軟かつシンプルにCSSを記述できるケースがでてきそうです。
この例のように構成要素が同等のコンポーネントが1画面内にある場合でも、画面のビューポート幅ではなく、それぞれのコンテナ幅から指定したスタイル適用ができます。
これまでは個別にコンポーネントに対してクラスを追加付与するなどの必要がありましたが、Container Queriesを使えばCSSのみでコンポーネントのスタイルを分岐させることができます。
使ってみる
これまで例で見てきたサイドバーとメインのエリアで、構成要素が同等のアイテムコンポーネントを簡素な形で書いてみました。
全体を div.wrapper
で囲い div.sidebar
と div.main
を左右に配置します。
それぞれのアイテムリストは ul.list
、コンポーネントは li.item
としてマークアップしています。
CSSのContainer Queriesの部分は下記のようになっています。
.list { container-type: inline-size; } @container(min-width:400px) { .item { display: flex; } }
親のコンテナとなる ul.list
に container-type: inline-size
を指定します。
デフォルトはテキストが縦並び( display: block
)になり、コンテナが400px以上の際はテキストが横並びになるようにするため、 @container(min-width:400px) {}
の中に li.item
が display: flex
するように記述します。
画面をリサイズしながら確認すると分かりやすいですが、ビューポート幅ではなくコンテナ幅によってスタイルの変更が適用されていることが確認できました。
まとめ
Container Queriesに初めて触れてみましたが、今後のレスポンシブデザインに対するアプローチに幅を持たせてくれるような機能だと感じました。
コンテナ幅でCSS指定ができることで、自由度が増す反面、デザインやコーディングのルールもより重要になってきます。
FigmaのAuto Layoutなどデザインツールで出来ることとの親和性も高そうですが、同時にデザイナーとの連携も密に行っていく必要がありそうです。
なかなかメリットのみ取り入れるのは難しいですが、特にコンポーネント指向の開発などではPolyfillを用いて取り入れることを検討してみても面白いと思いました。
:modal 擬似クラスを試してみた
:modal
擬似クラスとは
MDNでは、下記のように説明されています。
- JavaScriptの
showModal()
によって表示されるdialog
要素 - JavaScriptの
requestFullscreen()
によって表示されるフルスクリーン要素
先日リリースされたChrome 105、Edge 105でSafari、Firefoxを含めた主要ブラウザにサポートされる擬似クラスとなりました。
※ Can I use より
この記事では、業務で使用する頻度が高そうな 1. の showModal()
によって表示される dialog
要素 について検証を行いました。
基本的な使い方
まず、シンプルに「モーダルを開く」ボタンを押すとモーダルが表示され、「モーダルを閉じる」ボタンを押すとモーダルが非表示になる例を見ていきます。
簡単な例にはなりますが、3点のポイントを解説します。
モーダルは <dialog>
要素でマークアップする
<dialog> <!-- モーダルの中身です --> </dialog>
ボタン押下後に表示されるモーダルは <dialog>
要素でマークアップをします。
:modal
のスタイル調整
#my-modal:modal { /* モーダルのボックス自体 */ } #my-modal::backdrop { /* モーダル後ろの背景レイヤー */ }
CSSセレクターとしての :modal
は、モーダルのボックス自体、::backdrop
はモーダル背景レイヤーのスタイル指定となります。
JavaScriptで表示制御を行う
const modal = document.querySelector('#my-modal') const buttonOpen = document.querySelector('#button-open') const buttonClose = document.querySelector('#button-close') buttonOpen.addEventListener('click', () => { modal.showModal() // 表示 }) buttonClose.addEventListener('click', () => { modal.close() // 非表示 })
それぞれのボタンをクリックして、showModal()
で表示、close()
で非表示するようにします。
デザイン観点での検証
過去にモーダルのデザイン調整では次のような悩みがあったため、:modal
擬似クラスでは解消できるのかを検証します。
- モーダルと背景レイヤーのスタイル調整
- コンテンツ量が多い場合のボックス位置
- フェードイン・アウトで表示・非表示
- スマートフォンでの背景コンテンツがスクロールしてしまう件
※ 本記事執筆時点の Mac/Chrome、もしくは iOS/Safari の環境で再現した内容になります。
モーダルと背景レイヤーのスタイル調整
まずはモーダルと背景レイヤーに対してどのようなCSS指定が必要になりそうかを見ていきます。
#my-modal:modal { padding: 2.5rem; border: 0; border-radius: .5rem; background-color: #fff; box-shadow: 0 0 2rem .5rem rgba(0,0,0,.1); } #my-modal::backdrop { background-color: rgba(255,255,255,.8); } /* 以降省略 */
CodePenでのサンプル通り、モーダルのボックス自体へ枠線、角丸、背景色、影の指定が再現されました。
背景についても ::backdrop
疑似要素がブラウザのデフォルトで固定配置( position: fixed
)となっているため、背景色の指定のみで基本は問題なさそうです。
重なり順についても z-index
を必要とせずに意図通りにレイヤーが構成されています。
コンテンツ量が多い場合のボックス位置
モーダルの中のコンテンツ量が多い場合、どのような挙動になるでしょうか。
ブラウザのデフォルトCSSでは、モーダルはコンテンツ量に応じてなりゆきで可変しますが、例えば CodePenのサンプルのように max-width
と max-height
を
#my-modal:modal { max-width: 50vw; max-height: 50vh; }
と指定すると、モーダル外のマージンを保ち中央に配置されつつ、全体の横幅や高さが短い場合でもスクロールバーが表示されました。
ただ細かい点にはなりますが、モーダルコンテンツ内がスクロールするサイズで表示された際、スクロール位置が最下部に来てしまうようなので、気にすべきポイントではある印象です。
フェードイン・アウトで表示・非表示
デフォルトCSSの場合は瞬時にモーダルが表示・非表示されるため、フェードイン・アウトのアニメーションを付与できるかを検証します。
結果、:modal
に対しては transition
を指定した場合もアニメーションは動作しませんでした。
そこで多少強引な部分もありますが、JavaScriptでクラスを付け替えしつつ、@keyframes
を用いたCSSアニメーションでフェードイン・アウトを実現することはできました。
参考記事: dialog with animation by geckotang on CodePen
スマートフォンでの背景コンテンツがスクロールしてしまう件
スマートフォン端末で意図せず背景コンテンツがスクロールしてしまう現象は :modal
擬似クラスでは解消できるのでしょうか。
コンテンツのエリアの高さを取った上でモーダルを表示したところ、背景コンテンツもスクロールしてしまいCSSでは解消できませんでした。
現時点ではモーダル表示時にbody要素を position: fixed
にするなど従来通りJavaScriptを含めた対策が必要そうです。
まとめ
:modal
擬似クラスについて、主にデザインの観点から再現できること、できないことを検証しました。
個人的には思っていたよりも再現できることも多く、JavaScriptでの指定なしでEscキーでモーダルを閉じることができるなど他のメリットも多い印象でした。
記事内で再現が難しかった事項とのトレードオフにはなりますが、実際のプロジェクトでも要件によって使用の検討をして良いのかなという感触を得られました。
Next.js の Hello World から Vercel へのデプロイまで
React のフレームワーク Next.js の Hello World から Vercel へのデプロイまでを試してみます。
基本的には 公式のチュートリアル を参考にしています。
やってみた
環境作成
create-next-app コマンドでプロジェクト作成します。
$ npx create-next-app@latest ... ✨ Done in 9.20s. Initialized a git repository. Success! Created next-sample at /PATH/next-sample
この場合、聞かれるのはプロジェクト名のみです。
※ オプションで --ts
をつけると TypeScript を使ったプロジェクトになる。
※ ESLint のインストールエラーで Node.js を v14.13.0 → v14.17.0に変更した。
ローカルサーバー起動
ローカル環境の起動は
$ cd /PATH/next-sample $ npm run dev
のみ。
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
と出たらブラウザで http://localhost:3000 にアクセスして表示が確認できます。
ファイルの確認
create-next-app のみ行って生成されるのは最小構成の模様。
特にコンポーネントに分かれているわけではなく、 pages/index.js にトップページの記述がまとめてあります。
ルートにある next.config.js が設定ファイルで色々なプラグインを追加したりするとのこと。
Vercelへのデプロイ
$ git remote add origin https://github.com/USERNAME/next-sample.git $ git push -u origin main
次に Vercelのサイト でアカウント作成します。
アカウント作成してログイン後の画面、「Import Git Repository」から、先ほどプッシュしたGitHubのリポジトリを選択します。
リポジトリ選択後、デプロイ設定画面に移ります。
今回はデフォルトで問題ないのですが、ビルドコマンドや出力ディレクトリ、環境変数の設定ができそうです。
最下部に表示される「DEPLOY」ボタンをクリックすると・・・
ビルドやデプロイの進捗状況が表示された後、デプロイ成功の画面が表示されました。
ダッシュボードの「DOMAINS」のURLにアクセスするとサーバーにデプロイされていました。
感想
- Vue.js や Nuxt.js のCLIでのセットアップとあまり変わらずに立ち上げまではできました。
- Vercel でのデプロイはGitHubで管理しているプロジェクトはチュートリアルの通りのため簡単でした。
- ローカルのホットリロードやVercel上での画面表示が引くほど早かったです。
- Zero Config を謳っているとおり、必要最低限のファイルや機能から始めれそうだなと思いました。
中身のほうはマークアップするのに困らないくらいはこれからポチポチいじってみたいなと思います。
コンポーネント設計との上手な付き合い方
これはなにか
Webアプリケーション開発において、コンポーネント指向で開発を行うことがあります。
「コンポーネント指向で開発」とは、例えばこのインターフェース上のパーツ要素(=コンポーネント)は汎用的に使用するため
- どういう名称で
- どういう粒度で
- どういうバリエーションを用意して
他のページでも使いまわせるようにしましょう、といった具合で設計する工程を指します。
DocBaseのButtonコンポーネントの例。Figma + Atomic Design でUIコンポーネント集を作りました – KRAY Inc. より
これまで何度かコンポーネント設計の工程を挟むプロジェクトにマークアップエンジニアとして携わってきましたが、反省点も多く、未だに正解も見えない部分もあるのが実情です。
記事のタイトルでは偉そうに書いていますが、今回はデザイナーやエンジニアを含んだチームがコンポーネント設計をどのように行えば良さそうかを考えたいと思います。
※ ビジュアルデザイン、ディレクトリ構成、コードの実例等は本記事に含まれません。
※ 主にデザイン(情報設計、UI作成、マークアップ)から見た視点での内容です。
※ 基本的にはWebサイトではなくWebアプリケーション開発を想定しています。
コンポーネント設計のメリットと失敗例
メリット
まずはコンポーネント設計を適切に行えると、どのような利点があるのでしょうか。
- 画面のUIデザインが統一できる
- 責務毎に分割したコードを作れる
1.はデザイン職種、2.はエンジニア職種が感じることが多い利点になるかと思います。
後ほど触れますが、これは同時に職種によって気にする視点が異なるということも言えそうです。
これらの利点によって、ユーザーや開発組織にとってはどのようなメリットが生まれるのかを考えます。
より分かりやすくするため抽象的な表現になりますが、
- 一貫性
- 再利用性
- 拡張性
- 保守性
を高めることができるというのが私の現時点での所感です。
※ 話が広がるため深堀りしませんが、この議題で私の考えにしっくりくる記事は デザインシステムの目的を考える|seya|note になります。
ありがちな失敗例
逆にそんなコンポーネント設計の難しさを理解するために、ありがちな失敗例について見ていきます。
「コンポーネント設計 失敗」などでググると、下記の記事などが出てきました。
- Atomic Designをやめてディレクトリ構造を見直した話|食べログ フロントエンドエンジニアブログ|note
- AtomicDesignでAtomsの設計を失敗した話 - Qiita
- Atomic Designが刺さる現場・刺さらない現場 - ログミーTech
- Reactを使ったコンポーネント指向設計で、Atomic Designをやめようとしている話 - ITANDI Engineer Blog
どの記事もAtomic Designというメジャーな設計思想(フレームワーク)を使用した際の失敗体験になっています。
これはAtomic Designを使用すること自体が難易度が高いという点もあると思いますが、共通して書かれている設計の難しさとしては下記にまとめることができそうでした。
- 人によってルールや粒度がバラバラになりがち
- だんだんとこんなに細かく分割する必要あるの?という疑問が生まれてくる
- 運用が辛くなりがち
- エンジニアの意見を取り入れられていない場合など
- ひとつのコンポーネントや状態追加の作業がこんなに大変になってしまった、など
- エンジニアの意見を取り入れられていない場合など
- 最終的にコンポーネント設計を何のためにやっているのか分からなくなりがち
- 誰が幸せになるためにやり始めたんだっけ、など
これらは私も過去に感じたことがあった内容ですね。
以降ではこの問題をより解決に導くために、どのように取り組むべきかを考えていきます。
私の考え
コンポーネント設計は、こうして取り組んだほうが良さそうという現時点での私の意見は次の3点です。
- 関わる人全員で、粒度・分割の方法の認識を合わせておく
- どのような設計思想にも独自ルールは発生するものと考える
- デザイン観点よりも開発観点での正解を優先する
関わる人全員で、粒度・分割の方法の認識を合わせておく
コンポーネントの分割について最も難しさを感じるのは、人によって解釈の違いが多いことだと思います。
この齟齬を埋めるにはデザイナーとエンジニアの共同作業が必要で、どちらかが関わるだけだと難しい印象です。
ただ、アウトプットの最初の出処がワイヤーフレームやビジュアルの場合が多いため、コンポーネント設計の話題についてデザインが主導になることが多くなるのは必然だと思います。
また、なるべく初期の段階でエンジニアも含めたコンポーネント設計についてのディスカッションをできると良さそうです。後述しますが、最終的に開発側の観点を採用したほうがメリットが多いため、後戻りをできる限りしないで済むようにするためです。
情報設計やワイヤーフレームを引いた後の段階で、コンポーネントの粒度をどうするか、の話し合いが始まるケースがありますが、できる限りその前の工程の段階で、どのような分割方針で行うのかを皆でディスカッションできると、エンジニア側が設計思想の理解やディレクトリの想定等もしやすいのではないかと思います。
※ 【React/Vue.js】コンポーネント設計の(個人的)ベストプラクティス | Offers Tech Blog の「設計はデザイナーと協業で行う」項と同じ意見。
どのような設計思想にも独自ルールは発生するものと考える
いざコンポーネント指向で作っていきます、という段階で、
- 完全にオリジナルのルールを作るのか
- 何かしらの設計思想やフレームワークに沿って作るのか
大きく分けて2パターンになるかと思います。
この判断は、そのプロジェクトの内容や使用するフロントエンドのフレームワーク、メンバーの経験などによって決めることが多いでしょう。
「何かしらの設計思想やフレームワークに沿って作る」場合、Atomic Designは最も聞き馴染みのあるコンポーネントの設計思想と思いますが、先ほども紹介したとおり、上手く出来ずに断念した、ということもチラホラみかけます。
理由はそれぞれのプロジェクト内容に起因すると思いますが、Atomic Designという設計思想を使うという決定以外にも、本来は考慮したり決めたりする事が多いから、というのが多い印象です。
例えば、下記などが「本来は考慮したり決めたりする事」にあたるかと思います。
- Atoms と Molecules の境界はどこか
- 画面に出てくるすべてのパーツをコンポーネントとするか
- コンポーネントの各状態の種類はどれだけ必要か
- StoryBookなどでカタログ化をするのか
- 開発側の観点で不都合がないか
- ディレクトリ構成をどうするのか
- データ・状態の持ち方
- Propsの流れ
- テストのしやすさ
要は、Atomic Designを使っているから上手く開発が進められる保証はありません。
デザイン観点では破綻せずになんとか使えても、特に開発観点を考慮するとプロジェクト内での独自でルール決めが必要なことが多い印象です。
この「プロジェクト内での独自でルール決め」がそもそも発生しない想定で時間を取っていなかったり、チームのコミュニケーションが取りづらい状況で発生してしまうと段々と混沌として来てしまうなということを経験した記憶があります。
デザイン観点よりも開発観点での正解を優先する
デザイン側は、見た目的にコンポーネントをどのくらいの粒度や分割で、という意見を持ちがちですが、開発側の苦労(工数)を気にせず言っていることも多く、基本的には開発の意見を優先するほうが良いと思います。
特に先ほど「本来は考慮したり決めたりする事」の中の
- 開発側の観点で不都合がないか
- ディレクトリ構成をどうするのか
- データ・状態の持ち方
- Propsの流れ
- テストのしやすさ
など、なかなかデザイン観点だけでは考慮できないことが多いです。
※ デザイナーとエンジニアで考えるReactコンポーネント設計 - KitchHike Tech Blog の「"デザインとしての構造性" と "コードとしての再利用性"」項と同じ意見。
また、分割の粒度を小さくしすぎないことも重要と感じます。
コンポーネントを追加する際のコーディング時の作業として、下記などが挙げられますが、
粒度が小さいとどうしてもバケツリレー的が増えてきてしまうため、見通しやすさとのバランス次第で気持ち大きめを最小粒度とすることもアリかと思います。
さいごに
この記事を書くにあたり、他のブログ等も読みながら過去の経験を思い返しましたが、プロジェクトごとにも正解は異なると思うので難しい話題だなと感じました。
なかなか端切れの悪い記事にはなってしまいましたが、現状での考えはまとめることができて良かったと思います。
これからは特にデザインとエンジニアの境界の人がどのように立ち振る舞うべきか等、継続して考察していき以降のプロジェクトでも活かせればと感じました。
参考・関連リンク
- フロントエンドエンジニアが変える現場のモデリング意識/modeling-awareness-changed-by-front-end-engineers - Speaker Deck
- コンポーネントの分割に関する考察
- CSS設計における、すべてがコンポーネントであるという誤謬
- フロントエンドのコンポーネント設計に立ち向かう - Qiita
- デザイナーとエンジニアで考えるReactコンポーネント設計 - KitchHike Tech Blog
- 【React/Vue.js】コンポーネント設計の(個人的)ベストプラクティス | Offers Tech Blog
- Atomic Component Design | Rhyztech blog
- 『Atomic Design周りについての私見』の補足 - ponday blog
- 「Atomic Design × Nuxt.js」で破綻しにくい実装を目指すために決めたコンポーネント毎の責務 | aumo Tech Blog – アウモテックブログ
- Atomic Design ベースのコンポーネント設計を考えてみた - mya-ake com
- Salaries.jpのフロントエンド実装について ~ componentsとAtomic Design編 ~ - techtekt
Nuxt.jsでAPI通信なしの静的ファイルを書き出す
Nuxt.jsのComposition API、useStatic()
メソッドを使用して、API通信しない静的ファイルを書き出しできるかを試してみました。
経緯
開発案件でマークアップを担当する際に、開発リポジトリとは別にデザインチーム用のGitを作成するケースは多いです。
静的なHTML/CSSファイルを開発チームの方に組み込んでいただくフローになりますが、確認含めたコミュニケーションが煩雑になることもあったりします。
そのため開発のリポジトリ上で直接マークアップできたほうがいいとは考えているのですが、ディレクターやデザイナーに向けたデザイン内部のレビューが、プロジェクトによっては開発環境にデプロイされてからでないとできない、などいくつかの懸念点もあります。
そこで、ICSさんの API通信一切なし!Nuxt Composition APIで作る完全静的サイト という記事を読んで、API通信しない静的書き出しが可能であればS3にアップすれば前述の懸念は少なくなるかなと思い、この記事を参考に開発環境下ではAPI通信するサイトを静的書き出しできるのかを試してみました。
どうやるのか
Composition APIと非同期処理メソッド
前述のNuxt.jsのComposition API、useStatic()
メソッドを使用します。
まずComposition APIや useStatic()
が何かをざっくり解釈すると、
- Vue2まで使われていたのはOptions API
- Nuxt.jsでも2.13から
asyncData()
,fetch()
メソッドを使用してデータ静的化ができた
- Nuxt.jsでも2.13から
- Vue3からComposition APIが推奨化された
という流れになるようです。
Nuxt Composition APIでの静的化
useAsync()
, useFetch()
, useStatic()
の3つの非同期処理メソッドの違いについても前述のICSさんの記事が詳しいですが、ざっくり解釈すると
- 完全静的化で使用できるのは
useFetch()
,useStatic()
ということで、分かるような分からないような、メリット・デメリットはありますよ、ということだと解釈します。
API通信一切なし!Nuxt Composition APIで作る完全静的サイト より
今回はSSRのサイトを静的化したほうが目的に沿いそうなため useStatic()
を使用します。
やってみる
プロジェクト作成
create nuxt app でつくります。
Node.jsのバージョン:14.13.0
$ yarn create nuxt-app nuxt-composition-api-sample
Nuxt Composition API と Axios を使うためにパッケージをインストール。
$ yarn add @nuxtjs/composition-api @nuxtjs/axios
nuxt.config.js にそれぞれ追加。
... buildModules: [ ... '@nuxtjs/composition-api/module' // 追加 ], modules: [ ... "@nuxtjs/axios" // 追加 ], ...
同じく nuxt.config.js にgenerate時のターゲットを設定。
target: 'static'
ローカル起動してみる。
$ yarn dev
useStatic()
を使う
components/Tutorial.vue を適当にリネームします。
今回は記事通り Nuxt.jsの山のAPI を使うので、Mountains.vue としました。
CSS除いたコードは下記のような形になります。
<template> <ul> <li v-for="item in data" :key="item.title"> <h1>{{ item.title }}</h1> ... 省略 </li> </ul> </template> <script> import { defineComponent, useStatic, computed, } from '@nuxtjs/composition-api' import axios from 'axios' export default defineComponent({ setup() { const param = computed(() => 'hoge') const keyBase = 'fuga' const data = useStatic( async (param, key) => { console.log(param) // hoge console.log(key) // fuga-hoge const mountains = await axios.get(`https://api.nuxtjs.dev/mountains`) return mountains.data }, param, keyBase ) return { data } } }) </script>
useStatic()
の引数は下記のようになり、動的ルーティング(_id.vueなど)もできるようになっています。
API通信一切なし!Nuxt Composition APIで作る完全静的サイト より
できた画面は下記
generate する
yarn generate をしてみると、dist/ に 山のデータが入った fuga-hoge.json があります。
dist/ のHTMLをブラウザで見てみるとこのJSONを読みに行ってくれています。
所感など
記事通り試す程度はできましたが、動的ルーティングで試したり、もう少し useFetch()
との違いなどを理解できればもっと使えるような感じがします。
単純にAPIから何かを表示するだけのサイトは問題ないですが、DBやセッションが絡むサイトは難しそうな感じもしますね。。
Composition APIは機能が多く書き方もOptions APIとは結構変わっていたので、また触っていきたいなと思いました。
ほか参考にしたサイト
【イベント】うちのデザインレビューは“ここ”を見る
「うちのデザインレビューは“ここ”を見る【デザナレVol.11】」 を視聴したのでメモと感想を残しておきます。
目次・概要
ポートフォリオを介したマッチングプラットフォーム ViViViT を提供している 株式会社ビビビット さん主催の勉強会。
今回は3名の方が各社どのような目的や手法でデザインレビューを行っているかの発表。
個人の発表というよりは、ViViViT のサービスの宣伝感が強いイベントでしたが、特に興味のあった SmartHR 小木曽さんの登壇 についてまとめます。
- 前段
- 「デザイン」とは本来何を指す?
- デザインレビューとは?
- 品質とは何か?
- SmartHRのデザイン組織紹介
- 開発組織での事例
ポイント
前段
ソフトウェアの「デザイン」の重要性と期待値はますます高くなっている。
- 不確実性が増した世界で、優れたアウトプットは1人の知見だけで生み出せるものではない
- UIデザインだけに限らず、すべての「デザイン」という行為に当てはまる
「デザインレビュー」とは、設計品質を高め、理想を現実に近づける手段のひとつ
「デザイン」とは本来何を指す?
Wikipedia より
審美性を根源にもつ計画的行為の全般を指すものである。
つまりデザインの本来的な意味は、「UIやモックデザイン」ではなく 「設計や計画全般」 を指している解釈
デザインレビューとは?
このふたつの難解そうだが、今回は 「成果物の『品質』について精査・検証する儀式」 と解釈
品質とは何か?
- 「品質」という言葉は本来主観的なもの
- 評価するステークホルダーによって、品質の定義はさまざま
- 1人のデザイナーの「主観」で出した答えが、客観としての「品質」の良さを証明することは難しい
よって、
- プロダクトは誰のために作っているのか?
- ユーザーにとっての価値とは何か?
これらの疑問を開発者(プロダクトデザイナー含め)は常に持つべき、とのこと。
ユーザーの目線にたち、常に主観を疑い、検証していくため にデザインレビューが必要となる。
SmartHRのデザイン組織紹介
- コミュニケーションデザイングループ
- プロダクトデザイングループ
- プロダクトに関わるデザイン
- 発表者の小木曽さんはここに所属
- プロダクトに関わるデザイン
- プログレッシブデザイングループ
- ユーザーの多様性に関わるデザイン
開発組織での事例
主なレビューイベントとしては、
- スプリントレビュー
- 一般的なスクラムイベントのスプリントレビューと同じ(開発PBI含む全てが対象)
- プロデザレビュー会
- プロダクトデザイングループが中心になって行う
- 対象はSmartHRのプロダクトデザインに関わる成果物全て
の2つがあり、今回はプロデザレビュー会にフォーカスする。
プロデザレビュー会とは
目的
- プロダクトを中心とした成果物の精度・品質の向上
- 各プロダクトの状況把握と情報共有
- ナレッジや判断材料のシェアと標準化
レビュー対象
実施内容
- 完全オンライン
- 週1回1時間
- デザイナーが多めだが、他職能の人も参加やレビュー依頼あり
レビューのやり方
- レビューのお題を決めるのは、原則レビュー依頼者(レビューイ)
- レビューイが用意したアジェンダに沿って進行
- 特に手順に決まりなし
- ツールはFigmaが多めでMiroやGoogle Docs、スプレッドシート、実装画面等
実際の事例
- UIのバリデーション設計
- アクセシビリティ改善
- スペシャルサイトの設計
- RubyKaigi Takeout 2021 のUIデザインの設計
- エンジニアと協力してサイトの設計、意匠を決めた事例
- 非同期の改善案募集
- レビュー枠を待たずに非同期で改善提案が走ることもある
- 今回の例はページのレイアウトへの改善提起をSlackで実施
RubyKaigi Takeout 2021 のWebサイト
レビューで生まれる効果
デザインレビューの場作り
- デザインを見るってどんな観点でみればいいの?
- レビューはどんな粒度で持っていけばいい?
- レビューを受け取ったら必ず反映しないといけない?
- レビューでは何を言ってもいいの?
これらの疑問があると思うが、
レビューは「チームの知見や気づきを勝てに品質を向上し、よりよいインターフェースにたどり着くための儀式」という前提があり、
- レビューはレビューイの気づかないところに気づきを与えるもの
- レビューは押し付けではなく、ディスカッション
- レビューは考えを否定するものではない
という共通認識があるためうまく行えているとのこと。
詳細: デザインレビューの手引 | デザインプロセス | SmartHR Design System
関連: デザインシステムはピクセルグリッドと開発をすすめている
感想
もともとこのイベントを視聴した理由は、最近SmartHRへデザイン〜フロントエンド界隈で強い人が移っているため、その人たちがどのようなことをしたり、どのような組織構造で働いているのかに興味があったため。
またデザインレビューについて深堀りして他社の話を知ることのできる機会もあまりないと思ったため。
結果的に上記の目的はおおむね把握できてよかったです。
特にレビューの粒度など、受託と事業会社で大きく異なることはあるなとは思いましたが、場作り的なことは取り入れれる部分も多いと思うので今後の参考にしたいと思いました。