[Laravel5.5] SPAを構成するためにVue.jsをインストールして動かしてみる

# はじめに
SPA、いいですよね。モダンな感じで。
調べてみたらなんとLaravelでも`Vue.js`使ってSPA構築できるみたいじゃないですか！
というわけで早速導入するためのマニュアルを。自分用です。

## そもそも...
Laravelには強力な`blade`というビューファイルが存在します。
しかしながらモダンなWebサービスを構築しようと思った場合、jsなしには語れないみたいなところ、あります。
~~`jQuery`？知らない子ですね...。~~

もちろん**bladeファイルの中でjsライブラリをコールして使う**、みたいな構成でも全然いいのですが、例えば`Electron`噛ませてスマホネイティブにしようとしたところで大きな壁にぶち当たるような気がしました。
更に言えば構築していく上で、どうしても**bladeファイルをパーシャル化**（と個人的には呼んでいます、要するに部品化して一つのテンプレートファイルから`@include`することが増えた）していく機会が増えました。

こうなってくるとパーシャル化したファイルに流し込む**変数はどこから来てるんだっけ？**ってなったり、あれ？**どっから`@include`してんだ！？**ってなることが増えて、なんかいい方法ないかなあと調べたのが事の発端。

いろいろ調べてみたところ、`Angular`だったり`React`だったり、いろいろなjsライブラリがまあ見つかる見つかる。
どれにしようか悩みましたが、

+ Reactは大規模開発のほうが向いている
+ シンプルに処理するならVue.jsの方が簡単っぽい
+ Vue.jsは日本語ドキュメントが多いっぽい...
+ トレンド的なところで言えばVue.jsのがアツい

といった理由から今回はVue.jsを採用してみました。
複雑なことさせたかったらReactがいいみたいですが...。

## npmとは？
バックエンドから入った人なんで`node.js`とか名前は知ってるけど使ったことなーいな人だったので、この辺理解するのに少し迷いました。
どうもPHPで言うところの`composer`みたいな感じで、パッケージのバージョンを管理してくれるツールが`npm`ってことみたいです。
~~npmのバージョンが合わなくてVue.jsのインストール手間取ったのは別の話~~

# 手順
## 導入まで

### 前提

+ vagrant導入済み
+ Homestead構築済み

### バージョンチェック

```bash:console
node -v
# v8.9.4

npm -v
# 5.6.0
```

### npmを使ってライブラリをインストールする

これは恐らくwindowsのみなのですが、`npm install`だけだとコケる場合があるみたいです。
と言うか私の環境ではコケまくりました。
なので`--no-bin-links`オプションをつけてインストールします。
詳しくは[**こちら**](http://eiua-memo.tumblr.com/post/117361529158/npmvagrantvagrant%E3%81%AE%E5%85%B1%E6%9C%89%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E4%B8%8A%E3%81%A7npm)の方が詳しく解説されています。

```bash:console
npm install --no-bin-links

# node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js
# 的なエラーが出る場合があるので先にパッケージ入れて回避する
npm i cross-env --no-bin-links

# ルーティングをいろいろするためにvue-routerライブラリをインストールする
npm i vue-router --no-bin-links
```

### とりあえずテスト

コンソール叩いてコンパイルが成功するかテストしてみる。

```bash:console
npm run dev
#  DONE  Compiled successfully in 8746ms
```

## バックエンド設定変更

続いてルーティングの修正を行う。
SPAという名前の通り、基本的には一つのルートに対してアクセスし続けるもよう。
~~ちょっと待てこれ`Laravel DebugBar`使えなくね？~~
→フロントエンド側でいろいろモニョモニョできるツールがありました。後述します。

### routes/web.php修正

```php:routes/web.php
Route::get('/{any}', function () {
    return view('layouts/vue_app.blade.php');
})
->where('any', '.*');

```

これで`http://{host}/app`に接続したらSPA画面が表示されるようになったことと思います。

### resources/views/layouts/vue_app.blade.php作成

```html:resources/views/layouts/vue_app.blade.php
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravel + Vue.js</title>

    <link rel="stylesheet" href="{{ mix('css/app.css') }}"></script>

    <script>
      window.Laravel = {
          csrfToken: "{{ csrf_token() }}"
      };
    </script>
  </head>
<body>
  <div id="app">
      <div class="container">
          <router-view></router-view>
      </div>
  </div>
</body>
<script src="{{ mix('js/app.js') }}"></script>
</html>
```

### resources/assets/js/app.jsに追記

```diff:resources/assets/js/app.js
+ import Vue from 'vue'
+ import VueRouter from 'vue-router'
  require('./bootstrap');

  window.Vue = require('vue');

+ Vue.use(VueRouter)
+  const router = new VueRouter({
+   mode: 'history',
+   routes: [
+     { path: '/', component: require('./components/Index.vue') },
+   ]
+ })
- Vue.component('example-component', require('./components/ExampleComponent.vue'));

  const app = new Vue({
      router,
      el: '#app',
  });
```

## resources/assets/js/components/Index.vueを作成

```vue:resources/assets/js/components/Index.vue
<template>
  <div>
      <h1>{{ title }}</h1>
      <p>{{ message }}</p>
      <button @click="editButton" class="btn btn-primary">edit</button>
  </div>
</template>


<script>
export default {
  data() {
    return {
      title: "Laravel + Vue.js",
      message: "Initialize"
    };
  },
  methods: {
    editButton: function() {
      alert("edit");
      this.title = "Welcome to Vue.js!";
      this.message = "This is a sample application.";
    }
  }
};
</script>
```

## コンパイルする

```bash:console
npm run dev

# 何回もビルドコマンド投げるの面倒なんじゃって人はこれ
npm run watch-poll
```

これで`http://{host}/`に接続してみる。
動的に画面が切り替われば成功です。

![2018-03-13_15h07_11.png](https://qiita-image-store.s3.amazonaws.com/0/165355/ec79f3bb-1301-0ff1-ecd8-347a3b132489.png)
<div align="center"><p>↓</p></div>
![2018-03-13_15h07_16.png](https://qiita-image-store.s3.amazonaws.com/0/165355/427f65e3-e2ba-0eb7-2356-0f3f29cb0d99.png)

とりあえず俺の環境では動く。任務完了。

# 便利なデバッグツールたち
イカれた（いい意味で）ツールを紹介するぜ！

+ [**Laravel Debugbar**](https://qiita.com/sutara79/items/9fd442a81001842aeba1)
+ [**Vue.js Devtools**](https://qiita.com/hashimoto-1202/items/c81f5d4c271eef16d957)
+ [**Clockwork**](http://nextat.co.jp/staff/archives/181)

基本はGoogleのDeveloperツールが強力すぎて、あんまり必要ないっぽいですね。
かがくのちからってすげー！

# 所感
過去に`ajax`で自前関数作ったことあったけど`axios`便利すぎ。すっげーエレガントに書ける。
やっぱりフロントエンド苦手...本当は`TypeScript`入れて`Babel`通したい。
これを機にしっかり勉強していきたいところ。

この後の作業として、[**APIで認証取る記事**](https://qiita.com/tosite0345/items/2ae78d67a9d048224155)も書きましたので読んでいただければ幸いです。