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

スタディストのVue

mtakeda
November 19, 2023

 スタディストのVue

React vs Vue.js討論会〜好きで語る技術の話〜
https://timeedev.connpass.com/event/300375/

Youtube:
https://www.youtube.com/watch?v=j6cKBC3Gwe4

mtakeda

November 19, 2023
Tweet

Other Decks in Programming

Transcript

  1. スタディストのVue
    株式会社スタディスト
    2023/11/17

    View Slide

  2. 自己紹介

    View Slide

  3. Copyright © 2023 Studist Corporation. all rights reserved.
    自己紹介
    3
    竹田 求志です
    ● 基本機能強化チームのリーダー
    ● β版開発 → 価値検証 → 正式版開発の
    動きを続けている
    ● 趣味:音楽、犬、ゲーム
    ○ AC6を出してくれて嬉しい

    View Slide

  4. Copyright © 2023 Studist Corporation. all rights reserved.
    スタディストのサービス紹介
    4

    View Slide

  5. スタディスト Vueの歴史

    View Slide

  6. Copyright © 2023 Studist Corporation. all rights reserved.
    導入の経緯
    6
    ● 2018年秋、UIリニューアルを行うに当たってフレームワークを検討
    ● Angular、React、Vue.js を比較検討した
    ● Vue.js は習熟が比較的容易と判断された
    ○ → Vue.js を採用

    View Slide

  7. Copyright © 2023 Studist Corporation. all rights reserved.
    歴史
    7
    ● 2018年
    ○ Vue.js 導入
    ○ Storybook 導入
    ○ ドメイン駆動Vuexで複雑さに立ち向かう
    ● 2019年
    ○ Storybook による Visual Regression Test を導入
    ● 2020年
    ○ E2E導入
    ● 2021年
    ○ 機能開発を止めずに、6万行の TypeScript 移行を完了
    ○ Composition API導入開始
    ● 2022年
    ○ IE のサポートを終了せずに IE のサポートを終了
    ○ 機能開発を止めずに、500コンポーネント規模のVue 3 移行を完了
    ● 現在
    ○ Vuex → Pinia 移行を進めている

    View Slide

  8. 8
    UIリニューアルプロジェクトを振り返る
    なぜ習熟が容易だったのか

    View Slide

  9. 9
    HTML/CSSに馴染みがあって理解しやすかった
    シングルファイルコンポーネント(SFC)
    HTML感覚で書ける分岐とリストレンダリング

    View Slide

  10. Copyright © 2023 Studist Corporation. all rights reserved.
    SFC
    10

    COUNT: {{ count }}
    increment
    decrement

    <br/>import { defineComponent } from 'vue'<br/>export default defineComponent({<br/>data() {<br/>return {<br/>count: 0<br/>}<br/>},<br/>methods: {<br/>increment() {<br/>this.count++<br/>},<br/>decrement() {<br/>this.count--<br/>}<br/>}<br/>})<br/>
    <br/>button {<br/>font-weight: bold;<br/>}<br/>

    View Slide

  11. Copyright © 2023 Studist Corporation. all rights reserved.
    SFC
    11

    COUNT: {{ count }}
    increment
    decrement

    <br/>import { defineComponent } from 'vue'<br/>export default defineComponent({<br/>data() {<br/>return {<br/>count: 0<br/>}<br/>},<br/>methods: {<br/>increment() {<br/>this.count++<br/>},<br/>decrement() {<br/>this.count--<br/>}<br/>}<br/>})<br/>
    <br/>button {<br/>font-weight: bold;<br/>}<br/>
    ロジック(JavaScript or TypeScript)
    テンプレート(HTML)
    スタイル (CSS)

    View Slide

  12. Copyright © 2023 Studist Corporation. all rights reserved.
    HTML感覚で書ける分岐とリストレンダリング
    12

    COUNT: {{ count }}
    increment


    <br/>import { defineComponent } from 'vue'<br/>export default defineComponent({<br/>data() {<br/>return {<br/>count: 0<br/>}<br/>},<br/>computed: {<br/>errorMessage() {<br/>if (this.count > 10) {<br/>return '10を超えちゃだめです'<br/>}<br/>return ''<br/>}<br/>},<br/>methods: {<br/>increment() {<br/>this.count++<br/>}<br/>}<br/>})<br/>
    条件を満たした時だけ描画するv-if

    View Slide

  13. Copyright © 2023 Studist Corporation. all rights reserved.
    HTML感覚で書ける分岐とリストレンダリング
    13


    {{ message }}


    <br/>import { defineComponent } from 'vue'<br/>export default defineComponent({<br/>data() {<br/>return {<br/>messages: ['hoge', 'fuga', 'piyo']<br/>}<br/>}<br/>})<br/>
    配列の中身で繰り返し表示が出来る v-for
    SFC, v-if, v-for などにより完成形がイメージしやすい(直感的な宣言的UI)

    View Slide

  14. Copyright © 2023 Studist Corporation. all rights reserved.
    HTML/CSSに馴染みがあって理解しやすかった
    14
    HTML/CSSの経験に寄った開発者達
    ・フロントエンド専門がいない
    ・リニューアル前はRailsのerb(≒html/css)
    HTML/CSS 経験を活かした開発が出来るVue
    ・template, script, styleをまとめて書ける SFC
    ・直感的な宣言的UI
    Vue.js という選択は当時の状況にマッチしていた

    View Slide

  15. 15
    パフォーマンスの劣化を意識せずに開発出来た
    fine-grained Reactivity

    View Slide

  16. Copyright © 2023 Studist Corporation. all rights reserved.
    パフォーマンスの劣化を意識せずに開発出来た
    16
    ● Vue.js は影響のある箇所だけが再レンダリングの対象となる
    (fine-grained Reactivity)
    ● 親コンポーネントに変更があっても子コンポーネントは再レンダリングされない
    ● 仮想DOMなどの知識を持たずに機能開発に集中しても、パフォーマンスが劣化しづらい

    View Slide

  17. Copyright © 2023 Studist Corporation. all rights reserved.
    パフォーマンスの劣化を意識せずに開発出来た
    17
    ● Vue.js は影響のある箇所だけが再レンダリングの対象となる
    (fine-grained Reactivity)
    ● 親コンポーネントに変更があっても子コンポーネントは再レンダリングされない
    ● 仮想DOMなどの知識を持たずに機能開発に集中しても、パフォーマンスが劣化しづらい
    仮想DOMとか詳しくないけど、
    そこは Vue に任せて機能開発に集中だ!

    View Slide

  18. 18
    エコシステムに悩まずに進められた
    公式1択

    View Slide

  19. Copyright © 2023 Studist Corporation. all rights reserved.
    エコシステムに悩まずに進められた
    19
    ● Vueで使うエコシステムは基本公式一択
    ● スタディストでは以下を利用
    ○ Vuex (現在は piniaに移行中)
    ○ Vue Router
    ○ VueI18n
    ○ Vue Loader
    ○ Vue Test Utils
    ○ eslint-plugin-vue
    ● エコシステムを迷わずに決めて、進めることが出来る
    公式
    こっちでいいのね

    View Slide

  20. 20
    日本語ドキュメントを読みながら開発出来た
    他に比べて充実していた

    View Slide

  21. Copyright © 2023 Studist Corporation. all rights reserved.
    日本語ドキュメントを読みながら開発出来た
    21
    ● 当時Vue.jsの日本語ドキュメントが他に比べて充実していた
    ● 学習を進めるためにネットの海をあちらこちらに行く必要がなく、効率的に学ぶことが出来た

    View Slide

  22. UIリニューアル
    無事完遂
    22

    View Slide

  23. Copyright © 2023 Studist Corporation. all rights reserved.
    習熟が容易だった理由まとめ
    23
    ● HTML/CSSに馴染みのあるメンバーx HTML/CSSを経験を活かせるフレームワーク
    ● 機能開発に集中しても劣化しづらいパフォーマンス
    ● エコシステムが決まっている
    ● 日本語ドキュメントが豊富

    View Slide

  24. Copyright © 2023 Studist Corporation. all rights reserved.
    Vue3.x になった今どうか
    24
    ● HTML/CSSに馴染みのあるメンバーx HTML/CSSを経験を活かせるフレームワーク
    ○ このケースで素早く開発が始められるのは変わらない
    ● 機能開発に集中しても劣化しづらいパフォーマンス
    ○ 改善が続けられている
    ● エコシステムが決まっている
    ○ 実質1択状態なのは変わらず
    ■ 「Vue経験あり」の人はまず同じエコシステムの経験を積んでいる
    ● 日本語ドキュメントが豊富
    ○ 今もドキュメントしっかりしている
    ○ 他との差はあまり無い

    View Slide

  25. 25
    スタディストVue

    View Slide

  26. 26
    Composition API の活用してます
    共通化でなくても切り出してテストカバレッジ↑↑

    View Slide

  27. Copyright © 2023 Studist Corporation. all rights reserved.
    Composition APIの活用
    27
    ● 従来のOptions APIに加えてComposition APIが登場
    ※ React Hooks の Vue 版
    ● コンポーザブル関数として状態を持つロジックをコンポーネントから分離することで、コン
    ポーネント間での共通化や、ロジックのテストが行いやすくなった

    View Slide

  28. Copyright © 2023 Studist Corporation. all rights reserved.
    Composition APIの活用
    28
    <br/>import { useCounter } from '@/compositions/useCounter'<br/>const { count, increment, decrement } = useCounter(0)<br/>

    カウント: {{ count }}
    increment
    decrement

    Sample.vue
    import { ref } from 'vue'
    export function useCounter(initialValue = 0) {
    const count = ref(initialValue)
    const increment = () => count.value++
    const decrement = () => count.value--
    return { count, increment, decrement }
    }
    useCounter.ts
    <br/>import { ref } from 'vue'<br/>const count = ref(0)<br/>const increment = () => count.value++<br/>const decrement = () => count.value--<br/>

    COUNT: {{ count }}
    increment
    decrement

    Sample.vue
    コンポーザブル関数として切り出し
    Before After
    状態とロジックを使える

    View Slide

  29. Copyright © 2023 Studist Corporation. all rights reserved.
    コンポーザブル関数の嬉しいこと
    29
    ● 共通化が出来る
    ● テストが出来る!
    ● コードも読みやすくなる!
    import { useCounter } from '@/compositions/useCounter'
    describe('useCounter', () => {
    it('テスト!', () => {
    const { count, increment, decrement } = useCounter(2023)
    expect(count.value).toBe(2023)
    increment()
    expect(count.value).toBe(2024)
    decrement()
    expect(count.value).toBe(2023)
    })
    })
    useCounter.spec.ts
    状態とロジックが意図通りに動
    いていることをテストしやすい

    View Slide

  30. Copyright © 2023 Studist Corporation. all rights reserved.
    共通化の予定が無くても切り出す
    30
    <br/>



    共通化の予定は無いが、少々複雑なロジック
    他のコンポーネントでは使わないかもだけど、
    テスト/可読性のためにも切り出そうぜ!!

    View Slide

  31. 補足:
    useCounter は
    作らなくてもい〜んじゃない?
    31

    View Slide

  32. 32
    and more…

    View Slide

  33. 33
    Options API は今後もまだ使います
    シンプルなコンポーネントには良いよね

    View Slide

  34. 34
    <br/><script> + setup()<br/><script setup><br/>

    View Slide

  35. 35
    <br/><script> + setup()<br/><script setup><br/>Options API<br/>Options API & Composition API<br/>Composition API<br/>

    View Slide

  36. 36
    ● 昔から存在するコンポーネント
    ● 最近作られたシンプルなコンポーネント
    <br/><script> + setup()<br/><script setup><br/>Options API<br/>Options API & Composition API<br/>Composition API<br/>

    View Slide

  37. 37
    <br/><script> + setup()<br/><script setup><br/>Options API<br/>Options API & Composition API<br/>Composition API<br/>● 昔からあるコンポーネントにコンポーザブル関数を<br/>組み込んだもの<br/>● そこまで複雑でないコンポーネント<br/>

    View Slide

  38. 38
    <br/><script> + setup()<br/><script setup><br/>Options API<br/>Options API & Composition API<br/>Composition API<br/>● 複雑性の高いコンポーネント<br/>● <script setup> を試すために書かれたコンポーネントも<br/>少々存在する<br/>

    View Slide

  39. Copyright © 2023 Studist Corporation. all rights reserved.
    Options APIを使い続ける理由
    39
    ● すでに多くのOptions APIで書かれたコンポーネントが存在し、それをComposition APIに統一す
    るのはコストが高い
    ○ そもそも、複雑度か高くないコンポーネントを頑張ってComposition APIに移行するメリッ
    トは無い
    ● Options APIの方が書き慣れているエンジニアが多い
    ● Options APIが非推奨になる予定は無いと公式に記載されている
    → Options API, Composition APIどちらも利用可としている
    (とはいえ今後Composition APIでしか出来ないことが増える可能性もあり、様子見の段階)

    View Slide

  40. Copyright © 2023 Studist Corporation. all rights reserved.
    Options APIは公式にも価値を認められている
    40
    > Options API は、コンポーネントコードを書くときに「考えることを減らす」ことを可能にし、
    > それが多くのユーザーに支持されている理由です。
    > Options API は Vue の不可欠な要素であり、多くの開発者がVue を愛する理由にもなっています。
    > Composition API の利点の多くは大規模プロジェクトでこそ現れるものであり、多くの低~中程度の
    > 複雑性のシナリオにおいては Options API が堅実な選択肢であり続けることも理解しています。
    Vue公式ドキュメントより

    View Slide

  41. 41
    Vuex から Pinia へ移行してます
    ドメインの複雑さを隠蔽する用途は変わらず

    View Slide

  42. Copyright © 2023 Studist Corporation. all rights reserved.
    Vuexの使い方
    42
    ● Vuexをドメインの処理に集中させる
    ○ ドメインの複雑さはVuexに閉じ込める
    ● コンポーネントは理想的なモデルをVuexから受け取り、UI表現に集中する
    ● APIからドメインデータを取得する時以外は使わない

    View Slide

  43. Copyright © 2023 Studist Corporation. all rights reserved.
    Vuex
    43
    UI API
    store
    action
    getter
    mutation
    state
    API
    データ
    モデル

    View Slide

  44. Copyright © 2023 Studist Corporation. all rights reserved.
    Pinia
    44
    UI API
    store
    action
    state
    API
    データ
    モデル

    View Slide

  45. Copyright © 2023 Studist Corporation. all rights reserved.
    Vuex → Pinia
    45
    ● ドメインの複雑さを隠蔽するために利用する方針はそのままに、Piniaに移行中
    ○ コンポーネントがUIの表現に集中出来る
    ■ APIに変更があってもstore側で吸収出来る
    ○ 開発者としても利用用途が明確で使いやすい
    ● Vuexでボイラープレート的に記載していた色々が無くなって嬉しい

    View Slide

  46. コンポーネント分割はアトミックデザイン
    UIリニューアルプロジェクトから変わらず

    View Slide

  47. Copyright © 2023 Studist Corporation. all rights reserved.
    UIリニューアルの時点でアトミックデザインを採用
    47
    ● UIリニューアルプロジェクトの中で、コンポーネント分割の考え方を模索する中で導入
    ● 5つの要素に分解して考える
    ○ Pages (画面)
    ○ Templates (ページテンプレート)
    ○ Organisms (有機体)
    ○ molecules (分子)
    ○ Atoms (原子)

    View Slide

  48. Copyright © 2023 Studist Corporation. all rights reserved.
    UIリニューアルの時点でアトミックデザインを採用
    48
    ● スタディストではTemplateを使わない形で採用してます
    ○ Pages
    ○ Organisms
    ○ Molecules
    ○ Atoms
    ● 共通のレイアウトコンポーネントは別途使うこともある

    View Slide

  49. Copyright © 2023 Studist Corporation. all rights reserved.
    分割例
    49
    Pages

    View Slide

  50. Copyright © 2023 Studist Corporation. all rights reserved.
    分割例
    50
    Pages
    Organisms

    View Slide

  51. Copyright © 2023 Studist Corporation. all rights reserved.
    分割例
    51
    Pages
    Organisms
    Molecules

    View Slide

  52. Copyright © 2023 Studist Corporation. all rights reserved.
    分割例
    52
    Pages
    Organisms
    Molecules
    Atoms

    View Slide

  53. Copyright © 2023 Studist Corporation. all rights reserved.
    コンポーネントの境界を迷わないように
    53
    分類 用途 storeへのアクセス
    Pages ルート(URL)に対応したページ 可
    Organisms Moleculesを組み合わせて一連の機能を提供 可
    Molecules Atomsを組み合わせて単一の機能を提供 不可
    Atoms それ以上分割できないUIの最小単位 不可

    View Slide

  54. Copyright © 2023 Studist Corporation. all rights reserved.
    コンポーネント分割はアトミックデザイン
    54
    ● アトミックデザインを導入することで分割の基準を明確にしている
    ○ 作りやすい、探しやすい、管理しやすい
    ● 下位コンポーネントが上位コンポーネントを知る必要が無いので再利用しやすい
    ● storeにアクセス出来る層を限定することで、下位コンポーネントのテスタビリティが高い

    View Slide

  55. Copyright © 2023 Studist Corporation. all rights reserved.
    ドメインの複雑さを閉じ込めるVuex、アトミックデザインについての過去スライド
    55
    https://www.slideshare.net/shingosasaki3/teachmebiz-188542240

    View Slide

  56. https://studist.jp/

    View Slide