vue.jsの単一コンポーネントを使う

#この記事は
個人のメモです。もっと賢い方がいい記事を書いてます。
筆者はwindows10ユーザーです。

#知識編

###一般的に"Vue.jsを使う"と言うと
scriptタグでcdnを引っ張れば使えます。
ただし、せっかくVue.jsを使うなら単一コンポーネントを使って拡張性の高い開発がしたいと思いました。
このメモは"foo.vue"形式の単一コンポーネントファイルを作ってバンドルする方法でVueを使うためのものです。。

###Vue.jsの単一コンポーネントとバンドル
Vue.jsはnode.jsのexport/importモジュールを使い、コンポーネントごとに細分化された.vueファイルを
entry pointの.jsファイルを起点に新たな.jsファイルへまとめあげることができます。
これをバンドル、またはプリコンパイルと表現しています。

###世の中の記事の"Vue"が何を指しているのか

Vue.jsはもともとフロントで動く設計ですが、その.jsファイルを起点にしてサーバー側で
構築できるようにすればフレームワーク的にも使えるよね、という面があって伸びている言語だと思います。
Vue-cliを使うことで最初からフレームワークの骨格を作ることもできます。

色々使える分、記事によって書き手がどの角度から書いているのか判断する必要があります。

###Vueフレームワークの動かし方
serverの役割ができる.jsファイルを起動します。そうすると指定のポートで待機してくれます。
そこにhttpリクエストをすればモジュール群が動いてVueを組み立てて表示してくれます。

node.jsのパッケージ管理で使うpackage.jsonのscripts.startにserver役のモジュールを登録し、
npm startを実行するとVueフレームワークの動きが確認できます。

※これだとnpmが止まった瞬間にサーバーが落ちるので、リリースの時は別の方法を使うような気がしますが、今はこれで。

#環境構築編
###node.jsとnpmを入れる
windowsなので公式からダウンロードしてインストーラでインストールしました。
インストールしたらcmdを立ち上げて>node -versionと>npm -versionでバージョン確認。

###npm init
プロジェクトを作りたいディレクトリで>npm init。package.JSONをセットアップします。
自分の書いたものをパッケージとして公表しない場合は適当で。
entry pointだけ変な名前にすると後で面倒？デフォルトがindex.jsなのでデフォルトにします。

###npm install のコマンドについて
●install は i で代用可能
●-g : グローバルインストール、どの場所からでも参照されるようにインストールされる
●--save : パッケージとしてインストールされたときに、一緒にインストールさせる
●--save-dev : パッケージとしてインストールされたときにインストールさせない
●--save-devは -D で代用可能
標準で -g 付けている記事があるが、個人的にはグローバルインストールはしたくないので付けません。

###vue-cli
Vueフレームワークを自動で構成してくれます。が -g でないとcliのコマンドが使えず中止。

###webpack
vue-cliを使わなくてもwebpackで単一コンポーネントが使えます。
webpackと周辺のモジュールをインストール。

```sh
npm i -D webpack webpack-cli webpack-dev-server
npm i -D vue-loader vue-template-compiler css-loader style-loader
```
2018年11月14日現在vue-loader最新版は何故かうまく動いてくれないという書き込みが多数。
後の工程でスタックしましたがvue-loader@14 に変更してバージョンをダウンさせたところ先に進めました。

###設定ファイル

```webpack.config.js
// path is included in node standard modules.
// path.resolve can concatenate path and later directory name.
// And transrate relative path to absolute.
const path = require('path')

module.exports = {
  // Entry point : root/src/index.js
  entry: './src/index.js',
  output: {
    // Product directory : root/dest
    path: path.resolve(__dirname, 'dest'),
    // Product file name
    filename: 'bundle.js'
  },
  devServer: {
    // index.html and files which webpack has not to touch are in below : root/public 
    contentBase: path.resolve(__dirname, 'public')
  },
  // to use modules, install vue-loader, vue-template-compiler, css-loader, style-loader,
  // babel-loader, @babel/core and @babel/preset-env with npm.
  module: {
    rules: [
      {
        test: /\.vue$/, // If target file ends with .vue,
        loader: 'vue-loader' // use vue-loader
      },
      {
        test: /\.js$/, // If target file ends with .js,
        loader: 'babel-loader' //use babel-loader
      },
      {
        test: /\.css$/, // If target file ends with .css,
        use: ['style-loader', 'css-loader'] // use css-loader -> and then style-loader
      },
    ]
  },
  resolve: {
    // import alias './foo.vue' -> 'foo', './var.js' -> 'var'.
    extensions: ['.js', '.vue'],
    alias: {
      // To use vue-template-compiler
      vue$: 'vue/dist/vue.esm.js',
    },
  },
}
```

```package.JSON
{
  "name": "hogehoge",
  "version": "1.0.0",
  "description": "hogege.",
  "main": "index.js",
  "scripts": {
    "test": "hoge",
    "start": "webpack-dev-server --hot"
  },
  "author": "ming.hentech",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.1.6",
    "@babel/preset-env": "^7.1.6",
    "babel-loader": "^8.0.4",
    "css-loader": "^1.0.1",
    "install": "^0.12.2",
    "style-loader": "^0.23.1",
    "vue-cli": "^2.9.6",
    "vue-loader": "^14.2.3",
    "vue-template-compiler": "^2.5.17",
    "webpack": "^4.25.1",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10"
  },
  "dependencies": {
    "vue": "^2.5.17"
  },
  "babel": {
    "presets": [
      "@babel/preset-env"
    ]
  },
  "browserslist": "last 2 versions, not dead, maintained node versions"
}
```
"start": "webpack-dev-server --hot"
"babel": {"presets": ["@babel/preset-env"]},
"browserslist": "last 2 versions, not dead, maintained node versions"
この辺が追加になります。browserslistはこれでも動いてますが色々設定できる様子。

#動かしてみる編

###entry pointq

```index.js
import Vue from 'vue'
import App from './components/App'

new Vue({
  el: '#app',
  components: { App },
  template: '<app/>',
})
```

###単一コンポーネント

```app.vue
<template>
  <div>
    <p>Hello, World!</p>
  </div>
</template>
```

###HTML

```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Vue app</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="bundle.js"></script>
  </body>
</html>
```

bundle.jsって何？　→　webpack.config.jsのoutputを参照。

localhostの8080へアクセスして、hello, world!したら成功です。

以上。