VueでSPAの基礎を作ってみた

# はじめに
普段はアルバイトでReactを使ったWebアプリを開発しています。
今回はVueの勉強がてらにnode.js(express)とWebpackを使って、Hello,Worldを表示してみました。
Vueの実装は単一ファイルコンポーネント、ローカルサーバやwebpackはvue-cliを使わず自前で設定していきます。

# 主な環境
高度なことはやらないので、気にしなくていいと思いますが一応書いておきます。
macOS Mojave
node v10.16.0
express v4.17.1
webpack v4.36.1
webpack-cli v3.3.6

# ディレクトリ構造
```
public
　├ dist
　│　└ index.bundle.js
　└ index.html
static
　└ src
　　　├ components
　　　│　　└ Test.vue
　　　└ index.js
web
　└ server.js
node_modules
package.js
package-lock.js
webpack.config.js
```


# 1.nodeのインストール
nodeのインストール方法については他の記事を参考にしてください。
macなら[nvm](https://github.com/nvm-sh/nvm)、windowsなら[nvm-windows](https://github.com/coreybutler/nvm-windows)がおすすめです。

# 2.nodeのパッケージインストール
npmを初期化。

```
npm init -y
```

expressをインストールします。

```
$ npm i express -S
```

# 3.expressのローカルサーバを作る
```server.js
const express = require('express');
const app = express();
const path = require('path');

app.use(express.static(path.join(__dirname, '../public')));
app.listen(8080, () => console.log('vue_test 8080'));
```
```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>vue_test</title>
    <meta charset="utf-8">
    <meta name="description" content="">
    <meta name="author" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <div id="root"></div>
    <script type="text/javascript" src='./dist/index.bundle.js'></script>
  </body>
</html>
```

サーバを立てる

```
$ node web/server.js
```
ブラウザでlocalhost:8080にアクセスしてタブが「vue_test」になっているか確認。

# 4.webpackの設定
webpackとそのローダなどをインストール。

```
$ npm i -D webpack webpack-cli vue-loader vue-template-compiler css-loader style-loader babel-loader @babel/core @babel/preset-env
```

configを設定

```webpack.config.js
const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  mode: "development",
  entry: './static/src/index.js',
  output: {
    path: path.resolve(__dirname, './public/dist'),
    filename: 'index.bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          presets: [
            "@babel/preset-env"
          ]
        }
      },
      {
        test: /\.css$/,
        use: ['vue-style-loader', 'css-loader']
      },
    ]
  },
  resolve: {
    extensions: ['.js', '.vue'],
    alias: {
      vue$: 'vue/dist/vue.esm.js',
    },
  },
  plugins: [new VueLoaderPlugin()],
}
```

package.jsonにbabelを追加、scriptを編集

``` package.json
{
  "name": "vue_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "server": "node web/server.js",
    "build": "webpack"
  },
  "babel": {
    "presets": [
      "@babel/preset-env"
    ]
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.0.0",
    "style-loader": "^0.23.1",
    "vue-loader": "^15.7.0",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.36.1",
    "webpack-cli": "^3.3.6"
  },
  "dependencies": {
    "express": "^4.17.1",
    "vue": "^2.6.10"
  }
}
```

# 5.vueを書いていく
vueをインストール

```
$ npm i vue -S
```

後々、vue-routerも使いたいためindex.jsをエントリーポイントとしてコンポーネントをぶら下げるようにします(今回のコンポーネントは1つですが...)。

```index.js
import Vue from 'vue';
import Test from './components/Test';

const app = new Vue(
  Test
);
app.$mount('#root');
```
コンポーネントを記述

```Test.vue
<template>
  <div id="root">
    <p>{{ greeting }} World!</p>
    <p>hello</p>
  </div>
</template>

<script>
module.exports = {
  data: function () {
    return {
      greeting: 'Hello'
    }
  }
}
</script>

<style scoped>
p {
  font-size: 2em;
  text-align: center;
}
</style>
```

webpack実行

```
$ npm run build
```

もう一度localhost:8080にアクセスして「Hello World！」と表示されたら成功。

# 最後に
今回はvueを使ってhello worldを表示してみました。
主にvueの公式ページを参考にしていたのですが、どれもhtmlとjsファイルを対にして実装していてReactをやっている身としては困惑しました。
やっと見つけた単一ファイルコンポーネントのページも説明が少なく分かりづらい印象でした。

最初はvue-cliを使っていたのですが、あまりにも遅く無駄な機能が多かったので、webpackやサーバ部分も自前で実装しました。
最近のwebライブラリはvue-cli的な公式の開発環境が用意されていることには好感が持てますが、もう少しライトで使いやすければなーと思います。
次はrootingやflaxあたりをやってみたいと思います。

# 参考
[Vue公式](https://jp.vuejs.org/index.html)
[Webpackで始めるVue.js](https://log.pocka.io/posts/vue-webpack-tutorial/)