『令和』と書いて『Parcelでバンドル』と読む！ 今日からあなたもバンドラー

タイトルは釣りです。ただの便乗です。お気を悪くしたら、ごめんなさい。でも内容はあるように書いてみたつもりです。ぜひ読んでみてください。

# はじめに

前回「:link: [Vue.js+PHP+Slim Frameworkでログイン認証（コンパイルなしSPA）](https://qiita.com/isamusuzuki/items/7b592fc66e4a24392c0b)」という投稿をした者です。

Vue.jsの[単一ファイルコンポーネント](https://jp.vuejs.org/v2/guide/single-file-components.html)を使いたくなって、試しにParcelでバンドルしてみたら、ページの読み込みがえらく早くなって、さっそくバンドル派に鞍替えしたという話です。

「コンパイルなしのSPA」は初心者にはとっつきやすく、理解しやすいので、依然お勧めではありますが、最後の締めはParcelでバンドルするのがよいと思います。

ということで、新しいアプリを公開しています。

[:link: https://github.com/isamusuzuki/vue-parcel-slim-auth](https://github.com/isamusuzuki/vue-parcel-slim-auth)

![vue-parcel-slim-auth-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/48056/084f5e75-0338-eac9-4ba9-48002d2c2a94.gif)

## 何を作ったのか？

このWebアプリは、クライアントサイドは、[Vue.js](https://jp.vuejs.org/v2/guide/)と[Parcel](https://parceljs.org/)を使ってSPA（シングルページアプリケーション）を実現し、サーバーサイドは[Slim Framework](https://www.slimframework.com/)を使ってログイン認証を実現させています。

![diagram.png](https://qiita-image-store.s3.amazonaws.com/0/48056/ea3d9227-a983-363a-130c-d53547c29150.png)

## なぜParcelなのか？ なぜコンパイルしているのか？

Vueファイル（拡張子が`.vue`で、template/script/styleの3つから構成されている）を使いたかったからです。Webpackと比べると、Parcelは設定ファイルもなく、とてもシンプルです。「コンパイルなしのSPA」で勉強をはじめ、Vue-RouterとVuexが理解できた後に、Parcelでバンドルするのが一番の早道と思います。

### 私が考えるVue.jsを勉強していくときの最短ルート

1. Webpackのことは忘れる。説明している箇所は読み飛ばす
1. CDNだけでVue.jsを使ってみる。v-ディレクティブ, data, methodsがなんとなくわかったら次へ
1. CDNだけでaxiosを使ってみる。なんとなくAjax（非同期通信）が実現できたら次へ
1. 親子コンポーネントに挑戦する。なんとなく親子間コミュニケーションができたら次へ
1. JSモジュール機能（`<script type="module">`）を使って、JSファイルをインポートしてみる。インポートされるJSファイルは`export default { ... }`となっていればオーケー
1. CDNだけでVue-Routerを使ってみる
1. CDNだけでVuexを使ってみる
1. Vuexストアが窮屈になってきたら、モジュールに分割する
1. 非同期通信はモジュールのActionsにまとめる。Promiseを再勉強する
1. このあたりで[Vuexの公式サイト](https://vuex.vuejs.org/ja/)に掲載されている、「一方向にだけ流れているフローチャート図」が理解できるようになっているはず
1. 最後にParcelを使って、今まで書いてきたJSファイルをバンドルしてみる
1. 今まで書いてきたJSファイルをVueファイルで書き換えてみる。使うかどうかはあなた次第

## 【重要】はじめてParcelを使うときにつまずきやすいところ

### 1. バンドルするときは`vue.esm.js`を使う

CDNに慣れてしまっていると「とにかくvue.jsファイルを読み込めばいい」と考えがちですが、実は用途に応じて何種類か用意されていて、`import Vue from 'vue';`だけではエラーになります。package.jsonにaliasを追加することで、この問題はクリアーできます。

```json
{
  "alias": {
    "vue": "./node_modules/vue/dist/vue.esm.js"
  }
}
```

### 2. XamppのApacheサーバーと通信させるには、CORSエラーを乗り越える必要あり

`npm run dev`で開始されるParcelの開発サーバーは、クライアント側しかホスティングしません。サーバー側のAPIと通信させるには、XamppのApacheサーバーも起動しておく必要があります。

Parcelの開発サーバーは`http://localhost:1234`で、XamppのApacheサーバーが`http://localhost:80`だとすると、これは別サーバー同士の通信だと判断されます。このままでは、CORS（クロス・オリジン・リソース・シェアリング）エラーが発生して通信できません。

これを回避するために、Xamppサーバー側で、`httpd.conf`の`<Directory></Directory>`の中に、以下のおまじないを追加しておきます。

```text
Header set Access-Control-Allow-Origin "http://localhost:1234"
Header set Access-Control-Allow-Methods "GET, POST, DELETE, PUT, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
Header set Access-Control-Allow-Credentials "true"
```

### 3. サーバーのURLを自動的に切り替えられるようにする

Parcelの開発サーバーのときは、`http://localhost:80`という別サーバーにアクセスしますが、バンドルされた以降は、Xamppサーバーでも本番サーバーでも、同じサーバー内のアクセスになります。この切り替えは、settingsというモジュールを用意することで解決します。

settingsは、serverUrlというstateだけを持つ、とてもシンプルなモジュールです。別ファイルにするまでもないので、親コンポーネントの中で定義しています。

settings以外のモジュールは、`context.rootState.settings.serverUrl`でこの値を参照できます。

```js
// app1/Vue.app（親コンポーネント） 40行目
const settings = {
    namespaced: true,
    state: {
        serverUrl: location.host === 'localhost:1234' ? 'http://localhost:80' : ''
    }
}

// app1/modules/auth.js （モジュール）21行目
axios.post(`${context.rootState.settings.serverUrl}/auth`,
        payload
    ).then(response => {
        resolve(response);
    }).catch(error => {
        reject(error);
    });
```


### 4. ビルドの吐き出しはオプションを使いこなす

`--public-url`と`--out-dir`という2つのオプションは両方使います。

- `--out-dir`はビルドしたファイルの出力先です。ここではサーバー側のpublicフォルダ下を指定しています。
- `--public-url`はWebサーバーにおける自分がいる場所です。

```json
{
  "scripts": {
    "dev": "parcel app1/index.html",
    "clear": "rimraf dist ../application/public/spa/app1",
    "build": "parcel build app1/index.html --public-url /spa/app1 --out-dir ../application/public/spa/app1"
  }
}
```

## 最後に

ソースコードはGitHubに載せています。SPAに興味があり、PHPなら慣れている方はぜひダウンロードしてみてください。

[:link: https://github.com/isamusuzuki/vue-parcel-slim-auth](https://github.com/isamusuzuki/vue-parcel-slim-auth)

また、この記事が面白い、役に立つと思ったら、「いいね」してください。励みになります。