【Vue.js+Vuetify+vue-router】クリスマスに暇な新卒エンジニアが初めてポートフォリオを作成してホスティングしてみた

# はじめに

この記事は[駆け出しエンジニア Advent Calendar 2018](https://qiita.com/advent-calendar/2018/try-programming)の24日目の記事です。

24日目と言っても、参加者が全然おらず実質1日目の記事になります。

**駆け出しエンジニア**のAdvent Calendarですが、筆者は新卒未経験でエンジニアになったので9ヶ月経っています。
~~駆け出し名乗っていいのかは置いておき~~今回はタイトル通りVue.js + vue-router + Vuetify.jsを用いてSPAのポートフォリオを作成して、github pagesにホスティングしたのでその流れと苦労を投稿しようと思います!

[初心者が初めてvue.jsを触ってみる](https://qiita.com/kazuki5555/items/75fbe297bc77e12b6021)の地味な続編となっております。

基本的には今回@plus_kyotoさんの[フロント未学習の大学生が1週間でVue.jsを使ったポートフォリオを作った話](https://qiita.com/plus_kyoto/items/a01578b782f17f573510)をとても参考に真似させていただきました。ありがとうございます。

完成品[ポートフォリオ](https://kazuki5555.github.io/Portfolio/)
[Github](https://github.com/kazuki5555/Portfolio)

# インストール

node.jsがインストールしてある前提です。

```terminal

$ npm -g install vue-cli
# vue init webpack my-project

Project name my-project
? Project description A Vue.js project
? Author USER_NAME <MAIL_ADDRESS>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Set up unit tests No
? Should we run `npm install` for you after the project has been created? (recommended) npm

# Project initialization finished!
# ========================

To get started:

  cd my-project
  npm run dev

```

今回はテストとLinterは外しています。
`npm run dev`をすると

```terminal
Your application is running here: http://localhost:8080
```
と表示されたのでアクセスすると`ERR_SOCKET_NOT_CONNECTED`のエラーが。
どうやら社用パソコンのセキュリティソフトが悪さをしているそうなので
`config/index.js`を書き換えます。

```index.js
module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},

    // Various Dev Server settings
    host: 'localhost', // can be overwritten by process.env.HOST
    port:5678, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
```
もう一度`npm run dev`をすると

```terminal
Your application is running here: http://localhost:5678
```

アクセスします。

![スクリーンショット 2018-12-18 18.22.38.png](https://qiita-image-store.s3.amazonaws.com/0/251929/bfbb21c9-d160-a888-0f45-0048452288ae.png)

うまくアクセスできたようです。

# 実装
##下準備

* コンポーネントとページのディレクトリを分けるために、`pages`ディレクトリを`src`直下に作ります。
* vuetifyを使うために以下のようにmain.jsを書き換えます。

```vuejs

import Vue from 'vue'
import App from './App'
import router from './router'
import Vuetify from 'vuetify'

```

その後動くかの確認のためにトップページに`hello world`と表示するようにしてみます。
`pages`ディレクトリの中に`top.vue`を作成します。

```top.vue
<template>
  <h1>
    hello world
  </h1>
</template>

<script>
  export default {
    data () {
    }
  }
</script>

```

そしてルーティングの設定を書き換えます。`route/index.js`でルーティングの設定は行われているので

```index.js
import Vue from 'vue'
import Router from 'vue-router'
import top from '@/pages/top.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'top',
      component: top
    }
  ]
})

```

ルートディレクトリは`components/HelloWorld.vue`をimportしていましたが`top.vue`に変更。
これで読み込むと

![スクリーンショット 2018-12-19 10.42.14.png](https://qiita-image-store.s3.amazonaws.com/0/251929/05986fca-9914-9493-5491-f65399fb49f5.png)

しっかり`hello world`と表示されていますね。
これで下準備は完了です！

##コンポーネント作成

今回はなるべくコンポーネント化したかったのでまずはヘッダーから作成していきます。

```vuejs
<template>
  <v-toolbar
  dense
  color="black"
  ripple
  style="height: 70px;"
  >
    <v-layout justify-center fill-height>
      <v-toolbar-items class="hidden-sm-and-down">
        <!-- なぜか下のスタイル内では効かないためボタンごとにベタで高さ調整 -->
        <router-link to='/' class="link">
          <v-btn
          flat
          color="white"
          style="height: 70px; width: 100px; font-weight: bold;"
          >
            Top
          </v-btn>
        </router-link>
        <router-link
          class="link"
          v-for="item in items"
          :key="item.to"
          :to="item.to"
        >
          <v-btn
          flat
          color="white"
          style="height: 70px; width: 100px; font-weight: bold;"
          >
            {{ item.to }}
          </v-btn>
        </router-link>
      </v-toolbar-items>
    </v-layout>
  </v-toolbar>
</template>

<script>
export default {
  name: 'myHeader',
  data: () => ({
      items: [
        {to:'Profile'},
        {to:'Skill'},
        {to:'Works'},
        {to:'Contact'},
      ]
    })
}
</script>

<style>
.link {
  text-decoration: none;
}



</style>

```
vuetifyのツールバーを使っています。
また、リンク先のtoと表示項目を同じにすることでループを回すことでボタンを増やしていくという算段です。
なぜかstyleタグ内でのCSSがうまく効かなかったのでベタ書きなのと、`router-link`のtoをバインディングするためにコロンをつけなければいいけないのを忘れていて引っかかりました。

そして作成したヘッダーを表示するために`src/main.js`と`src/App.vue`を書き換えていきます。

```App.vue
<template>
  <div id="app">
    <headers></headers>
    <div id="content">
      <img src="./assets/logo.png">
      <router-view/>
    </div>
  </div>
</template>

<script>
import headers from './components/header.vue'
export default {
  name: 'App',
  components: {
    headers,
  }
}
</script>
```
`App.vue`では作成したコンポーネントを使用できるようにimportします。

```main.js
Vue.use(Vuetify, {
 iconfont: 'fa'
})
```
`main.js`にはこの文を追記します。
これ以降の開発は冗長になってしまうので割愛します。
githubをみていただけるとわかると思います。

この要領でフッターを作成し、ヘッダーのtoに当たるページを作成し、ページ内で使用するコンポーネント作成等を行って最終的にできたトップページがこちらです。

![スクリーンショット 2018-12-19 11.02.48.png](https://qiita-image-store.s3.amazonaws.com/0/251929/bc70ca99-a39f-e090-7e3f-788c7c780cb1.png)

背景画像はvurtifyからかっこいい画像を拝借しました。

# ホスティング

今回はGithub Pagesに、gh-pagesを使ってホスティングしました。

```terminal
$ npm install gh-pages
```
これでインストールできます。

そして`package.json`を書き換えます。

```package.json
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "build": "node build/build.js && gh-pages -d dist/",
    "deploy": "gh-pages -d dist"
  },
  "dependencies": {
    "gh-pages": "^2.0.1",
    "material-design-icons-iconfont": "^4.0.2",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "vuetify": "^1.3.5"
  },
```

これでデプロイします。

ただこれだけではcssとjsの読み込みがうまくいかないため@uriuriuriuさんの
[webpackでgithub pagesをdeployする際のハマりどころ(vue.js)](https://qiita.com/uriuriuriu/items/e764c4f1754d49754a0c)
[vue-routerのgithub-pages用設定](https://qiita.com/uriuriuriu/items/dc5ece0189c518c2e046)
を参考にしました。

ざっくり噛み砕くと、`gh-pages`のためにできた`dist`ディレクトリ内のindex.htmlに記載してあるCSSやJSへのパスが相対パスで、`dist/static`に飛んで欲しいのにプロジェクト直下の`static`を読み込もうとしていたエラーでした。

# 振り返って
## よかった点
* 新しい技術を触るのは純粋に楽しかった
* ビルド、デプロイ、パスなどあまり意識できてなかったところが弱点としてわかった
* へなちょこ作品でも達成感があった

##苦労した点
* 普段JSにめちゃくちゃ慣れている人間ではないので最初の理解が難しかった
* vuetifyが英語と日本語ごちゃ混ぜのドキュメントで理解に苦しんだ
* 誰にも何も聞かずに公開まで持っていくのは初めてだったので色々と苦労することが多々あった

# 参考
[Vue.js公式ドキュメント](https://jp.vuejs.org/)
[Vuetify公式ドキュメント](https://vuetifyjs.com/ja/)
@plus_kyoto様 [フロント未学習の大学生が1週間でVue.jsを使ったポートフォリオを作った話](https://qiita.com/plus_kyoto/items/a01578b782f17f573510)
@uriuriuriu様 [webpackでgithub pagesをdeployする際のハマりどころ(vue.js)](https://qiita.com/uriuriuriu/items/e764c4f1754d49754a0c)
@uriuriuriu様 [vue-routerのgithub-pages用設定](https://qiita.com/uriuriuriu/items/dc5ece0189c518c2e046)
@gcsungwoo様 [Vue.js概要【初心者】](https://qiita.com/gcsungwoo/items/15941c1ae0762fb566e6)
@567000様 [Vue.js を vue-cli を使ってシンプルにはじめてみる](https://qiita.com/567000/items/dde495d6a8ad1c25fa43)
@567000様 [Vue-routerを使って、SPAをシンプルにはじめてみる](https://qiita.com/567000/items/d6a7c694a370dc92e774)