Storybook でフロントエンド開発の治安を良くしていく話
https://gyazo.com/0478f03b0fa81b651ef7ceb48e00070f
この資料は Saitama.js vol.3 のLT資料です。
https://gyazo.com/5510d4e88c34b7dc94f91817952946e7
メニューのドキュメントアイコンより「Start presentation」クリックでプレゼンテーションが始まります
自己紹介
yamanoku.icon @ yamanoku
大山奥人, おおやまみちのく a.k.a やまのく
Twitter
GitHub
得意領域
マークアップ・フロントエンド・UIデザイン・アクセシビリティ
お元気ですか.fmパーソナリティ
takanoripと愉快にやってます
既婚で1児の父と猫🐈🐈🐈と犬🐶の飼い主
風太, 美月, うにちゃん
ジュン←New!
千葉県流山市在住
申し訳程度のsaitamajs要素
埼玉県に近い
車で10分圏内
新三郷にたまに出没します
コストコ最高!!!!!
中の人の所属先情報
株式会社クラウドワークス
クラウドソーシング「クラウドワークス」を中心としたWebサービス運営
https://gyazo.com/c9ab653c5ea3a08ab646801f7bcdc0b8
プロダクト本部 プロダクト開発部 プラットフォーム開発4グループ所属
エンジニアとして在籍
自称フロントエンドデザイナー
基本的にはフロントエンド改善への期待値があるらしいんですが色々あり各種やってます
テクニカルサポート対応したり
Terraformコード修正したり
Dockerfile修正したり
各種フロントエンドに関するレビューしたり
事業会社にはモノリシックバックエンドという世界があったりする
10年選手くらいの長いやつとか
フロントエンドはテンプレートエンジンやバックエンドコードにある
バックエンド言語の知識が居る
再現するにはサーバーを立ち上げないといけない
立ち上げるまで確認ができない
フロントエンド開発は Docker でサーバーサイド(+周辺サービス)を立ち上げないとできない
フロントエンドに集中した開発をするのに立ち上げるまでに時間がかかるのは…
立ち上がらないこともあると最悪
モチベーションが消滅してしまう!
ストレスを減らしてフロントエンド開発に集中する打開策はないか?
そうだ、Storybookを入れてみよう
https://gyazo.com/f7e906efa8e95e2ca3c9bad777205a1e
2020年12月頃の話
最初はフロントエンド開発の効率性だけを考えていた
バックエンドなんか触りたくねぇ!という強いモチベーション
バックエンドフレームワークに載らないディレクトリで管理
/frontend-tools/storybook みたいにして作成
もし不要ならポイーで良さそう
導入結果として全体の生産性が上がった
フロントエンド開発・バックエンド開発で集中と選択の開発ができた
会社から生産性向上施策として月間MVPとして表彰されました
Storybookを活用したアプリケーションリニューアル事案では全社MVTを受賞
施策チーム→技術的負債解消チームへ(2021/10〜)
ジャンヌというチーム名でやっていってます
https://gyazo.com/cc0ce5a30da2779a1fcf6f87da089a28
by MidjourneyAI
なぜ技術的負債返済に取り組むのか?
そのままにしておくとプロダクトの競争力の低下を招き、プロダクトライフサイクルより先に死期がくる
これを組織的に管理できるようにしていくのがジャンヌのミッション
フロントエンドの技術的負債返済活動
一時的に借りっぱなしだった技術的負債を開発しやすい主流なものへ移行していく
バックエンドと密結合になっている部分を分離する
Ruby on Rails erb => API + Vue.js へ
OpenAPIを使用したAPI実装
レガシーコードをモダンにしていく
CoffeeScript 辞めました - クラウドワークス エンジニアブログ
整備・剪定していく
npm packagesなどで使用していないものを削除・バージョンアップフォロー
新しい技術を使っていけるような周辺整備
絶賛 Webpacker を消そうとしています(まだまだ道半ば)
治安は悪いより良いほうがいいよね
技術的負債を返せることは心理的安全性を高くすることに繋がる
心理的安全性が高いのは治安が良いことに繋がる
治安の良さを手に入れていく
フロントエンド開発における治安の良さとは?
ブラウザ上で意図通り正しく挙動できているか(個人的見解)
ブラウザの再現+シナリオに沿ったコード
結合テスト部分の重視
ここを充実していきたい
テストの書き方・考え方
Testing Trophy
@kentcdodds: "The Testing Trophy" 🏆
A general guide for the **return on investment** 🤑 of the different forms of testing with regards to testing JavaScript applications.
- End to end w/ @Cypress_io ⚫️
- Integration & Unit w/ @fbjest 🃏
- Static w/ @flowtype 𝙁 and @geteslint ⬣
https://pbs.twimg.com/media/DVUoM94VQAAzuws.jpg
いわゆる寸胴型
E2E
結合テスト
この部分の厚みを増やす
今の取り組みたいイメージと合致しそう
ユニットテスト
静的解析
TypeScript
eslint
CIなどをもってPR上で確認できるようになるとGood
しかしテストを書こうにもどうやっていけばいいんだろうか?
黙って書けやと言われればそうなんですが…
テスト知識がない状態で始めるにしてもどう書けば良いのか…
なんかイメージしやすいいいツールないかな…
https://gyazo.com/f7e906efa8e95e2ca3c9bad777205a1e
もしかしたら Storybook によってテストが書きやすくなるのでは?
Stroybook にて書けるテストが充実してきた
結合テスト
スナップショットテスト
VRT
結合テスト(UIテスト)
「つながり」を見る
想定:フォームコンテナ的なもの
https://gyazo.com/318d838593b039892533f45eedf6acf5
Story をつくっていく
正常パターン
各フォームに入力→送信完了
mswを通じてAPI通信もできる
code:ts
export const createApiSucessMock = (): RestHandler<MockedRequest<DefaultBodyType>>[] => [
rest.post('/api/hello', (_req, res, ctx) => {
const json: ApiSuccessResponse<ApiVisitResponse> = {
status: "sucess",
status_code: 200,
data: {
message: "hello",
},
};
return res(ctx.json(json));
}),
];
エラーパターン(一例)
フォーム未入力の場合
https://gyazo.com/0b23b51b31005bab0a7f3becd3e0224c
バリデーションが通過していない
https://gyazo.com/51fad77b837d311b1e8bfb74f534a013
送信時のエラー時
Play function にて挙動チェック
v6.4.0 より導入
@storybook/addon-interactionsを使う
code:storybook.ts
import ExampleForm from './ExampleForm.vue';
import { screen, userEvent, waitFor } from '@storybook/testing-library';
import { createApiPublicVisitMock } from './mockfile';
export default {
title: 'pages/ExampleForm',
component: Login,
};
const Template = (args) => ({
components: { ExampleForm },
setup: () => ({ args }),
template: <ExampleForm v-bind=args />,
parameters: {
msw: {
handlers: createApiPublicVisitMock ,
},
}
});
export const ExampleSucessStory = Template.bind({});
ExampleSucessStory.play = async () => {
const TitleInput = screen.getByLabelText('タイトル', {
selector: 'input',
});
await userEvent.type(TitleInput, 'Saitama.js', {
delay: 100,
});
const DescriptionInput = screen.getByLabelText('説明文', {
selector: 'textarea',
});
await userEvent.type(DescriptionInput, '素敵なイベントです!', {
delay: 100,
});
const Submit = screen.getByRole('button');
await userEvent.click(Submit);
};
Jest側にも転用できるらしい(未体験)
code:test.js
describe("なんらかのフォーム", () => {
test("正常系パターン", async () => {
const { container } = render(<ExampleSucessStory />);
await ExampleSucessStory.play({ canvasElement: container });
// 送信完了できているとう体でチェック
expect(await screen.findByText("登録完了しました")).toBeInTheDocument();
});
});
Storybookで結合テストを書き、Jest側でテストケースとしてチェックをする
CIで怒られが確認できるよ!
スナップショットテスト
用途
DOMの最新状態・差分を比較できる
jest -u忘れずに(n敗目)
@storybook/addon-storyshotsを使う
Tips
Date はモックしておくとよい
Date.now() で取得すると異なってしまう
年が明けて1敗しましたyamanoku.icon
code:test.js
/**
* Date.now() を mock する。
* 現在日付を mock して欲しいときには、new Date() ではなく、new Date(Date.now()) と記述する。
* /
let dateNowOrig = null;
test.beforeAll = () => {
dateNowOrig = Date.now;
Date.now = () => new Date('2021-10-30T08:30:00.000Z').getTime();
};
test.afterAll = () => {
Date.now = dateNowOrig;
};
VRT
画像回帰テスト
実際にUIをスクリーンショットとして描画して差分がないかチェック
フロントエンド開発体験向上のために VRT を導入してみた - クラウドワークス エンジニアブログ
用途
修正時に差分をスクリーンショットで確認できる
レビュー時にお役立ち
ディレクトリの移動で差分がないことで安心したリファクタリングができる
レビューの安心に繋がる
種類
reg-suit,storycap
こちらを活用しています
Quramyさん、wadackelさんありがとう
Chromatic
Storybook謹製
従量課金制
storybook-chrome-screenshot
導入企業・サービス例
株式会社サイバーエージェント
Classi株式会社
Sansan株式会社
N予備校
Storybook駆動を得られるメリット
1つのツールを使ってテストを含めた一気通貫な開発ができる
Jestはロジック部分(hooks / composables)で集中できそう
実際のUIも見れるのでテストケースに慣れていない人でもイメージしやすい(かも)
デザインシステムを一緒に進めていくのにも有効
なんか最近流行ってますね
Spindle
https://spindle.ameba.design/
SmartHR Design system
https://smarthr.design/
デザインシステムのよる整備はデザインとしての負債解消文脈
トーンが揃っていない
スタイルの解釈の違い
なぜそのカラーを使っているのか
それらを確認できる環境をつくる
ドキュメントとして活用
正直 Storybookでなくてもよいけど、副次的な効果として
Storybookを使ってみて大変だったこと
addon を組み合わせるとアップデートが大変になっていく
そもそも単体のバージョンアップがしんどいという印象がある
iframe要素へのVRTが安定しない
storycapと相性が悪い
キャプチャが失敗することがある
依存しているpuppeteerがここを解消できていなそう
Sometimes browser process does not resolve capture image · Issue #545 · reg-viz/storycap · GitHub
ほか VRT だと問題ないんだろうか?
エラーが出た際にどこが問題あるか一見して分かりづらい
Storybook立ち上げ時にコケるがどこが間違ってるかがわかりづらい
なので描画できているStorybookファイルを複製して新しいのを書きがち
Storybook 関連が React.js 依存なところがある
node_modules に追加されて副作用が発生する可能性ががが
起動が重い
Nuxt.js環境で立ち上げが同じかそれ以下だったこともある
vitestを使ったものもある
6.5.0 からは設定ファイルがあるとそっちで読んでくれる
Alt Storybookの存在
Historie
Vue.js
ladle
React.js
そのほか
Alternatives to React Storybook - LogRocket Blog
Storybook運用に対して
React.js meetup #9より(2019/09/19のイベント)
Storybook腐りやすい問題
おうじ
絶賛腐ってる
運用していくしかない
SmartHRはここに投資していく
前職では
OKRにデザインシステムのメンテナンス目標に入れる
うさぎ
バージョンニングしてデプロイしてた
=バージョンが違うと差分がある
ライブラリのアップデートはしていかないといけない
どんな人でもコミットしてよい
社内OSSをするのは無茶だったのでメインメンテナを入れるようにした
はるけん
Storybook警察やってる
警察を置くのは大変?
運用メンバーというのは建てられると良いと思う
yamanoku.icon のところは有志活動ではあります…(たいへん)
まとめ
フロントエンド開発の効率性重視のために Storybook を導入したら
テストの拡充といった技術的負債の足掛けとして活用できそうなものだった
きちんとやっていくためにも運用についてもちゃんと考えていきましょう(現在進行形)
宣伝タイム
株式会社 クラウドワークス | バックエンドエンジニア(crowdworks.jp 技術負債解消チーム) | IT/Web業界の求人・中途採用情報に強い転職サイトGreen(グリーン)
組織的な技術的負債解消をやりたい人!一緒にやろうぜ!
Meetyやってます(業務関係ないカジュアル面談です)
フロントエンド領域の価値創造・開発体制つくりたい - 株式会社クラウドワークスの中の人のカジュアル面談 - Meety
フロントエンドの地位向上、技術的負債の解消や生産性向上に興味がある方とお話してみたいです!
フロントエンド開発×アクセシビリティ対応について語りたい! - 株式会社クラウドワークスの中の人のカジュアル面談 - Meety
アクセシビリティ対応についてもお話しましょう
Thank you for listening !
https://gyazo.com/4c1d0df4903765cc351797c10f903ba1