Vue.js ディレクトリ構成 色々試してみた

# なんじゃこれ

この記事はVOYAGE GROUPのサマーインターン、Treasure2018の修了生による[Treasure Advend Calendar 2018](https://qiita.com/advent-calendar/2018/treasure)の15日目の記事として書かれています。

# はじめに
`vue-cli`を使用するとディレクトリ構成に関しても良い感じにやってくれますが、そのままでは管理が難しい部分もあります。特に`components`以下に関しては役割別にディレクトリを分割していかないと渋くなりますよね。そこで今回は自分が今まで試してきたオレオレディレクトリ構成を紹介していこうと思います。
(ファイルは一部抜粋して掲載しています)

## 前提
```
$ vue --version
> 2.9.6
```

# Modules & Pagesパターン
```
.
├── App.vue
├── assets
├── components
│   ├── modules
│   │   ├── Footer.vue
│   │   ├── Header.vue
│   │   ├── Loading.vue
│   │   ├── UserCard.vue
│   │   ├── ReviewCard.vue
│   │   └── Graph.vue
│   └── pages
│       ├── Home.vue
│       └── User.vue
├── config
├── main.js
└── router
    └── index.js
```
初めてVue.jsでSPAを作る時に試したパターンです。Vuexも使わず、Vue.jsを覚えるために薄いアプリケーションを作るのに使用しました。

## 解説

### modules
再利用可能なコンポーネント群です。どんどんぶち込んでいきます。

### pages
`modules`を使ってページを構成します。再利用しないものならばここに直接書いたりもします。
`vue-router`から呼ばれます。
ボタンなどのアトミックな要素のデザインは`App.vue`内の`<style>`をscopedにせずにcssを書き、各コンポーネントからclassで指定して利用する形にしました。

## 感想
Vue.jsを覚えるのには十分だった。簡単なページ作るくらいなら良さそう。
コンポーネントが増えてくると辛くなりそう。

# Parts & Pages & Globalsパターン
```
.
├── App.vue
├── assets
├── components
│   ├── globals
│   │   ├── Footer.vue
│   │   └── Header.vue
│   ├── pages
│   │   ├── EditGist.vue
│   │   ├── Gist.vue
│   │   ├── Home.vue
│   │   └── User.vue
│   └── parts
│       ├── Comments.vue
│       ├── Editor.vue
│       ├── GistCard.vue
│       ├── IconButton.vue
│       ├── Loading.vue
│       └── UserCard.vue
├── main.js
├── router
│   └── index.js
└── store
    ├── index.js
    ├── modules
    │   ├── gists
    │   │   ├── actions.js
    │   │   ├── getters.js
    │   │   ├── index.js
    │   │   ├── mutations.js
    │   │   └── state.js
    │   └── users
    │       ├── actions.js
    │       ├── getters.js
    │       ├── index.js
    │       ├── mutations.js
    │       └── state.js
    └── utils.js
```
良い感じにVuexを使いたい時に使用した構成です。ここでのルールは一つだけ、Vuexとのやり取りは`pages` `globals`のみが行う（`parts`は行わない）ということです。
あらゆるコンポーネントからdispatchするとわけわからなくなった経験からこのルールを定めました。

## 解説
### globals
グローバルに使うコンポーネント群です。ヘッダーフッターとか。`App.vue`にてインポートされます。Vuexとのやり取りも行ってOKです。

### pages
`Modules & Pages`と同じく、ページを構成する役割を担います。Vuexとやり取りし、`parts`をインポートしてデータを渡してあげます。

### parts
再利用可能なコンポーネント群です。Vuexは使わずに基本は`props`からデータを貰い、それを元に処理をします。

### store
Vuexが入ります。`namespace`を使用し、ドメインごとに分けています。一つのファイルが肥大化するのを防ぐためです。

## 感想
小中規模でVuexを使うならば使いやすい印象でした。`parts`が増えてくるようだったら利用ケースごとにディレクトリを切ったり、後述するAtomic Designもどきを使うと良さそうです。

# Atomic Designパターン
```
.
├── App.vue
├── assets
├── components
│   ├── atoms
│   │   ├── Card.vue
│   │   ├── Button.vue
│   │   ├── LargeUser.vue
│   │   └── Loading.vue
│   ├── globals
│   │   ├── Footer.vue
│   │   └── Header.vue
│   ├── molecules
│   │   ├── Post.vue
│   │   ├── PostDesciption.vue
│   │   └── UserPosts.vue
│   ├── organisms
│   │   ├── PostTable.vue
│   │   └── UserProfile.vue
│　　　　　　└── pages
│       ├── posts
│       │   └── id.vue
│       └── users
│           └── id.vue
├── main.js
├── router
│   └── index.js
└── store
    ├── index.js
    ├── modules
    │   ├── posts
    │   │   ├── actions.js
    │   │   ├── getters.js
    │   │   ├── index.js
    │   │   ├── mutations.js
    │   │   └── state.js
    │   └── users
    │       ├── actions.js
    │       ├── getters.js
    │       ├── index.js
    │       ├── mutations.js
    │       └── state.js
    └── utils.js
```
Atomic Designのエッセンスを取り入れた、Atomic Designもどきです。初めからAtomic Designを目指したというより、規模が大めで、デザインしやすく、変更しやすい構成を考えた結果Atomic Designっぽくなった感じです。
自分の場合は再利用する場面がなさそうに感じたので`templates`がありません。

## 解説
### atoms
あとみっくなコンポーネント群です。ボタンとか。Vuexとやり取りしません。

### molecules
`atoms`のコンポーネントを利用して作るコンポーネント群です。Vuexとやり取りしません。

### organisms
`atoms`と`molecules`を利用して作るコンポーネント群です。**Vuexとやり取りします。**

### pages
`organisms` `molecules`を利用してページを構成します。Vuexとやり取りします。
nuxtっぽく、ルーティングと合わせる感じでディレクトリを切っています。

## 感想
粒度が適切になるので、「デザインのしやすさ」「変更の強さ」が担保される印象を受けました。しかし規模がそこまで大きくない、頻繁な変更が想定されないもので実践すると、逆にその粒度に悩まされることになりそうです。

# まとめ
タイトルにある通り、自分が試したことあるだけのオレオレな構成なので、参考までにという気持ちです！
そもそも、あらゆるパターンに最適な構成など存在しないので、臨機応変に色々な要素を取り入れて構成していくのが理想かなと思います。