弊社では将来的に弊社独自のデザインシステムの設計の後、既存のプロジェクトをすべて置き換えていく予定となっています。 私は、直近立ち上がった新規プロジェクトにて、将来的にデザインシステムに置き換わることが確実であることを前提として、変化に強く、テストコードによる品質を担保できるNuxt3プロジェクト開発基盤を作りましたので、本セッションにて共有できればと思います。
デザインシステムを後から導入する前提で作った変更に強いNuxt3 プロジェクト
View Slide
自己紹介
CVCV名前: みゅーとん趣味: VR, エレクトーン仕事: フロントエンド開発, 基盤開発,テックリードsns: twitter .. @_mew_ton私について
CVCV「ウェルネス産業を、新次元へ。」月額制サブスク店舗のための次世代 顧客管理・予約・決済システム「hacomono」を提供フィットネスクラブ・24時間ジム・ゴルフ・ダンススタジオ等の月額制店舗に適した会員管理・予約・キャッシュレス決済システム2019年3月にリリースし、これまでに1,400店舗以上が導入コロナ禍により、店舗は人との接触を削減する必要があり、導入件数は前年比10倍以上のペースで増えているhacomono について
CVCV今回のテーマ
CVCVデザインシステムを後から導入する前提で作った変更に強いNuxt3 プロジェクト
変更に強い とは
CVCVあとから Design System に乗り換えるならAtomic Design を意識して実装してあれば変更点は少なくて済む (?)極論
CVCV開発メンバー全員にAtomic Design を意識してもらうのは結構難しいしかし、そうもいかない
CVCV1. Atomic Design のような構成を機械的に維持できる2. 影響範囲がわかる状態“変更に強い” means
CVCVやったことを順番に解説していきます
CVCV- Nuxt v3.0.0-rc.6- Vue v3.2.37前提
やらかさない Atomic Design
CVCVパーツ単位でUIデザインを設計/実装する手法Atomic Design ?
CVCV見たことある図出典: atomic design, https://bradfrost.com/blog/post/atomic-web-design/
CVCVNuxt3 の構成だと・・出典: atomic design, https://bradfrost.com/blog/post/atomic-web-design/src/pages 配下に作っておけば良さそう(src/components/pages があっても良)src/components/* に全部置く・・?
CVCV素直な導入はできない
CVCVやりがちな失敗● organism ? molecule ? 区別がつかない● molecule が fetch してるのを “コードレビューで” 防ぐの辛い● 結局 src/components/* 以下が汎用 / 非汎用 が混在してカオスになる
CVCV実装向けの Atomic Design の拡張Atoms, Molecules(Vue3 components)Atoms, Molecules を区別しないNuxt3 とは違うプロジェクトでVue3 Component として実装将来的に Design System に置き換えていくOrganisms(Nuxt3 src/components/*)Domain, Nuxt Contextに紐付くなら粒度に限らず Organisms粒度に限らず fetch 等して良いNuxt3の src/components に配置
CVCVプロジェクト開始時点のフォルダ構造
CVCV構成のメリットAtoms, Molecules(Vue3 components)composable が auto-import されないDomain データの interface が Nuxt 側にあり参照できない汎用的な作りがほぼ強制されるOrganisms(Nuxt3 src/components/*)composable を利用できる汎用コンポーネントがほぼ作られないDesignSystem を import して使う体制に近い
Design System もどきを作る
CVCVおさらいAtoms, Molecules(Vue3 components)Atoms, Molecules を区別しないNuxt3 とは違うプロジェクトでVue3 Component として実装将来的に Design System に置き換えていくOrganisms(Nuxt3 src/components/*)Domain, Nuxt Context (vue-routerなど)に紐付くなら粒度に限らず Organisms粒度に限らず fetch 等して良いNuxt3の src/components に配置
CVCVアウトプットAtoms, Molecules$ start-storybook……………………Organisms$ nuxt dev……..………………………..
CVCV● Storybook に表示されるものを正とする● (Storybook 6.4以上) play function もなるべく実装● 必要ならドキュメントも作る● Chromatic を利用して Visual Regression Test を実施vue3 component 実装ルール
CVCV
CVCVChromatic ?Chromaticは、UIフィードバックの収集、ビジュアルテスト、ドキュメンテーションを自動化することで、開発者は少ないマニュアル作業で迅速にイテレーションを行うことができます。出典: chromatic, https://www.chromatic.com“”CI/CD で Storybook を使った Visual Regression Test ができる
server/api を必ず作る
CVCVserver/api ?Server Routesserver/api 配下にファイルを配置し、 API エンドポイントを定義できる出典: Nuxt3 guide, https://v3.nuxtjs.org/guide/features/server-routes/
CVCV● すべての API コールは server/api の処理を経由すること (※)● server/api では、取得データを ViewModel に変換して返すfetch 処理実装時のルール※ Sentry, DataDog などは除く
CVCV● 取得データ → ViewModel 変換処理が client の js に含まれない● useFetch が型安全● useFetch, useAsyncData によるキャッシュフローが実装しやすくなる● ViewModel だけを考慮する mock サーバが作れるserver/api を必ず実装する メリット
CVCVMock サーバの作り方
CVCVserver/api の モックサーバの作り方 1
CVCVserver/api の モックサーバの作り方 2import type { Health } from '~/lib/models/health'declare const url: stringexport default defineEventHandler(async (event) => {// 外部から値を取ってきてconst result = await $fetch(url)// ゴニョゴニョいじって返すreturn toHealth(result)})function toHealth(response: unknown): Health {// …}src/server/api/health.get.ts test/server/api/health.get.tsimport type { Health } from '~/lib/models/health'import mock from './health.json'export default defineEventHandler(() => {// モックデータの JSON を返すだけreturn mock})
CVCVnuxt.config.ts に以下を追記 ..server/api の モックサーバの作り方 3// おまじないhooks: {'nitro:config': (config: NitroConfig) => {if (isTest()) {const testServer = resolve(__dirname, './test/server')config.srcDir = testServerconfig.scanDirs = [testServer]}}}
最低限の E2E テストを実装
CVCVNode.js 上からブラウザを操作するライブラリE2Eテストによく使うVisual Regression Test が可能Playwright
CVCV実装するテストコードimport { test, expect } from '@playwright/test'test.describe('/login', () => {test('画面表示', async ({ page }) => {// ページを表示await page.goto('./login')// 描画完了を待つawait page.waitForLoadState('domcontentloaded')// 描画結果をスナップショットテストawait expect(page).toHaveScreenshot()// おわり})})test.afterEach(async ({ page }) => {await page.close()})
CVCV● モックサーバモードで Nuxt を立ち上げる● 全ページについて、ページにアクセスして Snapshot するだけをテスト● それ以外のテストは、やりたければやるE2Eテスト実装のルール
CVCVCV
まとめ
CVCV1. Atomic Design の構成を機械的に維持できる2. 影響範囲がわかる状態“変更に強い” means (おさらい)
CVCV1. Atomic Design の構成を機械的に維持できるAtoms, Molecules は Nuxt3 の src/components/* に実装しないVue3 プロジェクトに切り出して作るまとめ
CVCV2. 影響範囲がわかる状態Atoms/Molecules を Storybook, Chromatic で VRTPages を Playwright で VRTPlaywright でのテストの実装を容易にするにはserver/api の実装とモックサーバ化があると楽まとめ
CVCVこの構成にした他のメリット● テスト実装工数が少なめ● OpenAPI → GraphQL に変更する予定としても変更に強い● フロントエンド初心者には比較的易しめ○ Vue, Nuxt の難易度の低さも相まって○ Storybook のお作法を覚えてね という辛さはあるまとめ
CVCVCV終