5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NuxtでAtomic Designを実践

Last updated at Posted at 2020-05-27

はじめに

初めまして。
WELLNESONE JAPAN株式会社(株式準備中)代表取締役CTOの@yusuke_1011です。
自社で一からサービス開発を行う際に実践した構成をここに記しておきます。

こちらの記事は、「Nuxt + Docker + CIrcleCI + Storybookという構成でAtomic Designにて開発していく」の第2章となります。

一般的な内容も多くありますが、説明用のサンプルではなく、実際にプロジェクトで導入した内容にはなるので、オリジナルな部分もある程度含んでしまいます。その点ご了承くださいませ。

全体構成

Nuxt + Docker + CIrcleCI + Storybookという構成でAtomic Designにて開発していく

  1. Nuxtの開発環境をDockerで構築
  2. NuxtでAtomic Designを実践(←今ここ)
  3. Nuxt + Storybookでコンポーネントを管理
  4. Storybookを用いたテスト(ストラクチャルリグレッションテスト編)
  5. Storybookを用いたテスト(ビジュアルリグレッションテスト編)

前提

  • Atomic Designの概念を理解できている
  • Nuxtで開発環境の構築ができている
  • Nuxtのプロジェクト構成、各ディレクトリの意味が理解できている

NuxtとAtomic Design

Atomic Designではコンポーネントを以下のように分割します。

  • Atoms
  • Molecules
  • Organisms
  • Templates
  • Pages

皆さんご存知の通り、Nuxtにもデフォルトでpagesディレクトリが存在します。
ただ、Atomic DesignのpagesとNuxtのpagesは同じ意味にはなりません。
Nuxtのlayouts + pagesがAtomic Designのpagesのような感覚になります。
(これも厳密には違いますが。。)

ですので、後述の通り、本プロジェクトではディレクトリ構成を純粋なAtomic Designとは少し変更することにしてあります。

VuexとAtomic Design

では、どのコンポーネントがVuexを意識するのが良いのでしょうか。
基本的にはpagesのみがVuexを意識し、他はすべてpropsで値を受け渡すという意見が多いかと思います。
ただ、そうすると、かなり記述が冗長になってしまうことが難点だと思います。

ディレクトリ構成

以上を踏まえ、本プロジェクトでは以下のようなディレクトリ構成にしました。

src
└── components
    └── atoms 
    └── molecules
    └── organisms
└── layouts
└── pages

賛否両論あるかとは思いますが、templatesを廃止しています。
components内のコンポーネントは

  • vuexやrouterなどの存在を知らないし、依存もしない
  • propsで受け取った値を表示させる
  • emitで親要素にコールバック関数を受け渡す

という運用になります。
例えば、atomsであれば、button.vueのような最小単位のコンポーネントを格納しますが、コード例としては以下です。

button.vue
<template>
  <button
    :shadow="shadow"
    :lighten="lighten"
    :disabled="disabled"
    :class="[
      'btn',
      'btn-size-' + size,
      'btn-type-' + type,
      'btn-color-' + color,
      'btn-align-' + align
    ]"
    @click="clickHandler"
  >
    <span :class="['btn-text', 'btn-font-' + font]">
      <slot>
        <span v-if="iconLeft">
          <font-awesome-icon :icon="iconLeft" class="fa-fw" />
        </span>
        <span v-if="btnText">{{ btnText }}</span>
        <span v-if="iconRight">
          <font-awesome-icon :icon="iconRight" class="fa-fw"/>
        </span>
      </slot>
    </span>
  </button>
</template>

<script>
export default {
  props: {
    shadow: Boolean,
    lighten: Boolean,
    disabled: Boolean,
    size: String,
    type: String,
    color: String,
    align: String,
    font: String,
    iconLeft: Array,
    iconRight: Array,
    btnText: String
  },
  methods: {
    clickHandler(e) {
      if (this.disabled) {
        return;
      }
      this.$emit("click", e);
    }
  }
}
</script>

(styleの部分は省略しています)

Storybookによるコンポーネント管理

Atomic Designを実践する上では、コンポーネントのカタログを作りたくなってきます。
これにStorybookを使用します。
storybookは

  • React
  • Vue
  • Anguler

で幅広く使用できるコンポーネント開発環境です。
元々はスリランカのスタートアップがReact用に開発したらしいです。
Storybookを使用することで、プロダクトと切り離した環境でコンポーネントを開発できるので非常に便利です。
また、コンポーネントのテストにも活躍します。
こちらの導入に関しては、また次節でご説明します。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?