$30 off During Our Annual Pro Sale. View Details »

BASEにおける Vueコンポーネント設計の現在

simezi9
October 30, 2019

BASEにおける Vueコンポーネント設計の現在

Vue.jsアーキテクチャリング勉強会
https://cw-engineers.connpass.com/event/146975/

で話したスライドです

simezi9

October 30, 2019
Tweet

More Decks by simezi9

Other Decks in Programming

Transcript

  1. © - BASE, Inc.
    BASEにおける
    Vueコンポーネント設計の現在

    View Slide

  2. ⾃⼰紹介
    © - BASE, Inc.
    松原 佑介
    フロントエンドエンジニア
    2018年9⽉BASE⼊社
    : simezi

    View Slide

  3. BASEのプロダクト
    © - BASE, Inc.
    ネットショップ作成サービス
    「BASE」
    ショッピングアプリ
    「BASE」
    Payment to the People,
    Power to the People
    MISSION

    View Slide

  4. © - BASE, Inc.
    2019年10⽉25⽇
    マザーズ上場しました

    View Slide

  5. BASEのフロントエンド開発の現状
    © - BASE, Inc.
    サーバーサイド:PHP, Go
    フロントエンドエンジニア:6名
    フロントエンド:Vue.js, TypeScript, Sketch
    デザイナー:8名
    (2019年10⽉時点)

    View Slide

  6. フロントエンドチームは何をしてきたか
    © - BASE, Inc.
    • 管理画⾯刷新プロジェクト開始で
    jQueryからVue.js+TS化
    • SPAではなく、⼤きな機能単位で
    MPA(Multi Page Application)化
    • 内製のUIコンポーネントライブラリ
    の作成
    ࣍ͷ5೥Λࢧ͑ΔVue.js੡UIίϯϙʔωϯτϥΠϒϥϦΛҭͯΔ

    View Slide

  7. 今ではプロジェクト開始から約1年半
    © - BASE, Inc.
    本⽇はそこで追加で得られた
    コンポーネントづくりの知⾒
    について話します

    View Slide

  8. おしながき
    © - BASE, Inc.
    BASEでのコンポーネント設計
    Storybookの整備
    個別のコンポーネントの実装

    View Slide

  9. © - BASE, Inc.
    ①BASEでのコンポーネント設計

    View Slide

  10. コンポーネントの種類
    © - BASE, Inc.
    Atomic DesignとContainer Componentの考え⽅を
    借りて、役割に応じて⼤きく4つに分類
    . Container Component
    . Presentational Component
    . Common Presentational Component
    . Atom Component ( UIライブラリ )

    View Slide

  11. コンポーネントの種類
    © - BASE, Inc.
    コンポーネントを役割に応じて⼤きく4つに分類
    . Container Component
    . Presentational Component
    . Common Presentational Component
    . Atom Component ( UIライブラリ )

    View Slide

  12. Container Component
    © - BASE, Inc.
    • Atomic DesignでいうPageに相当
    • API通信、Storeへのアクセスを⾏うことができる 
    唯⼀のコンポーネント
    • 複数のPresentational ComponentやContainer
    Componentを束ねる役割
    • ContainerComponentの中に多少のUIを持つこと
    は認める

    View Slide

  13. コンポーネントの種類
    © - BASE, Inc.
    コンポーネントを役割に応じて⼤きく4つに分類
    . Container Component
    . Presentational Component
    . Common Presentational Component
    . Atom Component ( UIライブラリ )

    View Slide

  14. Presentational Component
    © - BASE, Inc.
    • Template/Organismに相当
    • 副作⽤を持たず、与えられたプロパティを表⽰するだ
    けのコンポーネント
    • 具体的なビジネスロジック‧表現に紐づくため再利⽤
    性は考えないコンポーネント
    • ContainerComponentと
    PresentationalComponentはディレクトリを分け
    ず、名前で区別する

    View Slide

  15. コンポーネントの種類
    © - BASE, Inc.
    コンポーネントを役割に応じて⼤きく4つに分類
    . Container Component
    . Presentational Component
    . Common Presentational Component
    . Atom Component ( UIライブラリ )

    View Slide

  16. Common Presentational Component
    © - BASE, Inc.
    • Template / Organism / Moleculeに相当
    • Presentational Componentの中でアプリケーション
    の内部で頻出するデザインのパターンを定義する
    • 例)全体のヘッダーやページのパンくずとタイトル
    • 具体的なコンテキストがない抽象的で使い回しができ
    るコンポーネント群

    View Slide

  17. コンポーネントの種類
    © - BASE, Inc.
    コンポーネントを役割に応じて⼤きく4つに分類
    . Container Component
    . Presentational Component
    . Common Presentational Component
    . Atom Component ( UIライブラリ )

    View Slide

  18. Atom Component
    © - BASE, Inc.
    • Atomic DesignでいうMolecule/Atomに相当
    • 個別のアプリケーションにとどまらず、サービス全体
    で流⽤できるような⼩さいコンポーネント群
    • form部品やbuttonなどの利⽤頻度がたかいもの
    • スタイルの局所的な上書きも許容できるように
    Scoped CSS / CSS Modulesを使わない
    • コンポーネント外との関係を決めるスタイルは当てな
    い 例) margin, float, z-index‧‧‧etc

    View Slide

  19. 概念図
    © - BASE, Inc.

    View Slide

  20. 概念図
    © - BASE, Inc.
    ΠϕϯτͷྲྀΕ

    View Slide

  21. 概念図
    © - BASE, Inc.
    ֎෦ͱͷ௨৴͸
    Container͚ͩͰߦ͏

    View Slide

  22. 概念図
    © - BASE, Inc.
    Common/Presentational
    ͸ͲͪΒͰ΋਌ʹͳΕΔ

    View Slide

  23. © - BASE, Inc.
    ②Storybookの扱い

    View Slide

  24. Storybookに求められる2つの役割
    © - BASE, Inc.
    .サンドボックス
     実際のコードに対してどう動くかを試す環境
     実装の際のエンジニア向けガイドとしての働き
    .カタログ
     提供されているコンポーネントを網羅的に⾒る
    どちらかの要素が⽋けたものが出来上がりがち

    View Slide

  25. サンドボックス性の⾜りないStorybook
    © - BASE, Inc.
    昔ながらのUIカタログの機能しかないケース
    • やりたいことはわかっても渡すべきprops、
    キャッチすべきevent、他コンポーネントと
    の組み合わせなど、実装に必要な情報が⾜
    りない
    • storybookに置く意味があまりない
    • 実装を意識しないならsketch上にあるだけ
    でいい

    View Slide

  26. カタログ性の⾜りないStorybook
    © - BASE, Inc.
    実装者が作るだけ作って満⾜してしまった
    ケース
    • コンポーネントが⼀個おいてあるだけ
    想定されている使い⽅が伝わらない
    • knobsに⼤量のパラメータ
    パラメータの組み合わせもわからず、作った
    ⼈にしかわからない。特にデザイナーとはコ
    ミュニケーションが難しい
    協業の場として機能しない

    View Slide

  27. storybookを機能させるために
    © - BASE, Inc.
    • Knobsに頼りすぎない
    • あくまでknobsは補助
    • UIとして利⽤するパターンはなるべく⼀覧できる
    ように(= カタログ)
    • 実装に必要な情報はきちんと書く(=サンドボックス)
    • コンポーネントごとにREADME.mdを⽤意する

    View Slide

  28. コンポーネントごとのREADME.md
    © - BASE, Inc.
    @storybook/addon-notesで読み込む
    必要な情報
    • 簡単なサンプルコード
    • 動作の仕様
    • Propsの値、型、デフォルト値
    • Eventの発⽕タイミング、payload
    • slotの名前
    • scoped-slotで渡される値 …etc
    将来的には@storybook/addon-docsで
    markdownを活⽤できるようになるはず
    (現在はVueのサポートがWIP)

    View Slide

  29. コンポーネントのレイヤ別に必要なこと
    © - BASE, Inc.
    ίϯϙʔωϯτͷछྨ Χλϩάੑ αϯυϘοΫεੑ
    Container
    Storybook্ʹ
    ొ࿥͠ͳ͍
    Presentational ௿ ௿
    Common ௿ ߴ
    Atom ߴ ߴ
    レイヤの低い抽象的なコンポーネントほど説明が必要

    View Slide

  30. © - BASE, Inc.
    ③個別のコンポーネントの実装

    View Slide

  31. フロントエンドの性質
    © - BASE, Inc.
    • フロントエンドのコードはライフサイクルが短い
    • 修正=全取替であることが珍しくない
    • ドメインロジックに落としづらい細かい分岐の連続
    • 例)ある⼀箇所だけ「0円」を「無料」にしたい…
    • 共通化しても仕様がすぐに変わってしまう

    View Slide

  32. © - BASE, Inc.
    コンポーネントで作る最⼤の
    メリットは共通化ではなく
    責務の分離

    View Slide

  33. コンポーネントの責務の分離
    © - BASE, Inc.
    • コンポーネントで作ることでスタイル、マークアッ
    プ、スクリプトを外部に影響しない形でカプセル化
    できる
    • 作る側もとにかく疎結合を優先して、類似コードの
    重複を恐れない。
    • 本当に必要なパターンと確定したら共通化する
    • いつでもコードの塊で捨てられる状態をキープする

    View Slide

  34. 実装のtips① props
    © - BASE, Inc.
    • ObjectやArrayを型に指定するのはなるべく避ける
     特にTSを採⽤している場合にはPropTypeを使う
    props: {
    deliveryInfo: {
    type : Array as PropType
    },
    payment: {
    type : String as PropType,
    }
    },

    View Slide

  35. 実装のtips① props
    © - BASE, Inc.
    • HTML標準に沿った名前、汎⽤的な名前をつかう
    ίϯϙʔωϯτར༻ऀ͔ΒΈͨࣗવͳΠϯλʔϑΣΠεΛ৺͕͚Δ
    name: 'AppInput',
    props: {
    id: String,
    name: String,
    type: String,
    value: {
    default: '',
    type: [String, Number],
    },
    placeholder: String,
    }

    View Slide

  36. 実装のtips②event
    © - BASE, Inc.
    • イベント名にカラフルな語彙を使わない
    BASEͰ͸ {Πϕϯτͷಈࢺ}:{Πϕϯτͷର৅} ͱ͍͏ϑΥʔϚοτΛར༻͍ͯ͠Δ
    ྫ) update:someValue
    • XMLͷ໊લۭؒͷϑΥʔϚοτʹ߹Θͤͯಈࢺ+(͋Ε͹໨తޠ)ͷܗࣜ
    • ಈࢺͷޠኮΛߜΓγϯϓϧͳ୯ޠΛ࢖͏͜ͱͰݟ௨͕͕͋͠Δ
    • ಛʹಈࢺ͸਌ίϯϙʔωϯτʹ
    ዁౓ͨ͠Πϕϯτ໊Λ͚ͭͳ͍
    @click:search="openSearchBox"
    @change:all="checkAll"
    @change:sortOrder="onChangeSortOrder"
    @change:editMode="onChangeEditMode"
    @change:keyword="onChangeKeyword"
    @search="onSearch">

    View Slide

  37. 実装のtips②event
    © - BASE, Inc.
    • イベントのpayloadにObjectを使う
    • RORO(Receive an object, return an object)
    • emitするプロパティが増えても壊れにくい
    // emit͢Δଆ
    this.$emit('change', { enabled: defaults, dirty: false })
    // ड͚औΔଆɹ
    updateShippingFee({ enabled, dirty }) { // Objectͷ෼ׂ୅ೖͰड͚औΔ
    this.$store.useCase(new EditItemDetail()).updateShippingFee(enabled, dirty)
    }

    View Slide

  38. 実装のtips③style
    © - BASE, Inc.
    • classを条件分岐や処理で渋滞させない
    • すべてclassで表現するとパターンが増えたときに
    爆発しがち
    // Մಡੑͷ௿͍ίʔυ

    View Slide

  39. 実装のtips③style
    © - BASE, Inc.
    • ⼀時的な状態に依存するスタイルはdata-*やaria-*
    と属性セレクタの組み合わせで当てる
    • 例) ローディング中、選択中か、など

    .foo {
    &[aria-selected="true"] { color: $green; }
    &[aria-selected="false"] { color: $gray; }
    }

    View Slide

  40. 実装のtips④scoped-slot
    © - BASE, Inc.
    コンポーネントの内部状態を⼀元管理するコンポー
    ネントが欲しくなる場合にはscoped-slotを利⽤す

    例)
    • テーブルのヘッダとリストの結びつき管理
    • モーダルのトリガとなるコンポーネントとモー
    ダルのコンテンツ

    View Slide

  41. 実装のtips④scoped-slot
    © - BASE, Inc.
    モーダルのサンプル


    දࣔ͢Δ


    ίϯςϯπ


    View Slide

  42. まとめ
    © - BASE, Inc.
    • コンポーネントでいちばん⼤事なのは責務の分離
    • 特にContainerとPresentationalなコンポーネン
    トの役割わけをきっちり守るのは重要
    • いつでもコード(特にUI側)を捨てられるように。
    • Storybookには広い利⽤者に向けたおもてなしの⼼
    が必要
    • ちょっとした⾶び道具的な修正でコンポーネントの前提が壊れても泣かない

    View Slide

  43. © - BASE, Inc.
    ありがとうございました

    View Slide