Vue CLI 3でSPAではなくMPA(複数エントリーポイント)のプロジェクトを作成する

SPA(シングルページアプリケーション)での使用例や記事は多く見られますが、MPA(マルチページアプリケーション)での利用例・情報は公式含めあまり多く見られませんので記録しておきます。

# 目的
そもそも、主流のSPAではなくMPAでVueプロジェクトを構成しようと思った理由は下記になります。(Vue.jsは学習中なので間違っている可能性もあり)

- Django REST frameworkとの連携を考えた際に、ルーティングをDjango側で制御することでSPAにおけるSEO対策を考えなくてよい。
- プロジェクトのディレクトリを各ページごとに分けることで開発中の見通しがよくなるのではと考えた。

# 参考
以下の記事を参考にしました。
[vue-cli 3.0で立ち上げたアプリに複数のエントリーポイントを用意する](https://qiita.com/Toxoxi/items/5dde43b4e7e6f3dc5cf4)
[multiple pages in Vue.js CLI](https://stackoverflow.com/questions/51692018/multiple-pages-in-vue-js-cli)

# 事前知識
Vue CLI 3からはwebpackをVueがラップしてプロジェクトを生成するので、Vue-cli 2まではあった、複数エントリーポイントの設定を記述する`webpack.config`が生成されません。
代わりに`vue.config.js`というファイルをプロジェクトのルートに新規作成し、その中にMPAの設定を書いていきます。
今回は、2ページだけの簡単なMPA(TOPページ + USERSページ)です。ページを増やす必要があれば同じ手順でどんどん増やしていけば問題ないはずです。

# プロジェクトを作成する

#### 1. vue createでプロジェクトの準備
ここはどうやってもSPA向けのプロジェクト構成でファイル群が生成されますのでデフォルト設定なりマニュアル設定なりお好きな方で。(当たり前ですが`vue router`はインストールしません)

```shell
$ vue create mpa-project
```
そうすると見慣れた以下のような構成でプロジェクトが作られたかと思います。
今回は、`src/App.vue`と`src/main.js`は使用しません。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42337/4ace287c-c2f2-5fdd-ede0-afa5702d9b6c.png)

#### 2. エントリポイントとなるページ、ルートコンポーネントを作成する
まずはディレクトリをまとめて作成します。
`src`直下に新たに`pages`というディレクトリを作成します。
さらに`pages`の中には各ページが分かる名称でディレクトリを追加します。
今回用意するページは1.トップページ(top)と2.ユーザーページ(users)です。

```shell
# プロジェクトのルートディレクトリに移動しておいてください
$ cd mpa-project
#　topとusersディレクトリを作成
$ mkdir -p src/pages/top src/pages/users
```
続いて、エントリポイントとなるファイル、そしてそれに読み込まれるルートコンポーネントを用意します。

```shell
# エントリポイントを作成
$ touch src/pages/top/main.js src/pages/users/main.js
# それぞれのルートコンポーネントを作成
$ touch src/pages/top/Top.vue  src/pages/users/Users.vue
```
`src`ディレクトリ以下はこのようになりました。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42337/f8a4d321-9078-ba66-7181-7ba681bcac32.png)

#### 3. 各ファイルの編集
トップページと、ユーザーページはそれぞれ`TOP`,`USERS`とテキスト表示するだけのページとなりますので、トップページ用の2ファイルだけをここに記載します。ユーザーページ用の2ファイルは適宜内容を書き換えてください。

###### top/main.js
```js
// TOP main.js
import Vue from 'vue';
import Top from './Top.vue';

Vue.config.productionTip = false;

new Vue({
  render: h => h(Top),
}).$mount('#app');
```

###### top/Top.vue
```vue
<template>
  <div id="app">
    <p>TOP</p>
  </div>
</template>

<style lang="scss">
</style>

<script>
</script>
```

#### 4. テンプレートファイルの編集
エントリーポイントのjsファイルを読み込むテンプレートファイル(public以下)をそれぞれのページ分作成していきます。
内容はVue CLIで生成されたテンプレートファイルの内容を丸写しなのでここでは省略します。
Django RESR frameworkと組み合わせた時には、これらのファイルのビルド先をDjangoのtemplatesディレクトリになるよう設定すれば良いでしょう。

```shell
$ touch public/index.html public/users.html
```


#### 5. vue.config.jsの作成・編集

さぁ終わりも近づいてきました。
事前知識の項目でも書いた、multi-pageモードの設定を記述する`vue.config.js`を作成・編集していきましょう。

```shell
$ touch vue.config.js
```

###### vue.config.js

```js
module.exports = {
  pages: {
    top: {
      entry: 'src/pages/top/main.js', // エントリーポイントとなるjs
      template: 'public/index.html', // テンプレートのHTML
      filename: 'index.html', // build時に出力されるファイル名
    },
    users: {
      entry: 'src/pages/users/main.js',
      template: 'public/users.html',
      filename: 'users.html',
    },
  },
};
```

以上でファイルの作成・編集は終了です。デフォルトで作成されていたSPA用のファイルは削除しています。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42337/29a55a99-3c66-ac49-4d8a-ea6596a4b356.png)

# モジュールのインストールと`vue.config.js`ファイル変更の反映
参考にしたQiita記事に記載してあった、2つのパッケージ(multi-pageモードの動作に必要らしい)の追加します。
また、`vue.config.js`の`pages`の項目を変更した際には反映が必要とのことなので、実行します。

```shell
# モジュールの追加
$ npm install --save-dev html-webpack-plugin preload-webpack-plugin
# 変更の反映
$ vue inspect
```



# 動作確認

以下のURLにアクセスしてそれぞれのページ内容が表示されたらOKです。
途中にも書きましたが、テンプレートとなるhtmlファイルのbuild先をDjangoなどのフレームワークのテンプレートディレクトリに指定すれば、連携も簡単かと思います。

```shell
$ npm run serve
```

- トップページ `localhost:8080`
- ユーザーページ `localhost:8080/users`