おもいだすときによむめも

おもいだしたいことがあるときにかきます

Nuxt.js + Vuetifyで手っ取り早くポートフォリオサイトを作る

できたのがこれ。

プロジェクト作成

create-nuxt-appでやると楽。
最近はnpmの性能が上がっているらしいので脱yarnする。
デザインは見た目や保守性が良くなればUIフレームワークを使った方が良い派なのでVuetifyを使う。
チーム開発でもないのにスペースなどに一々文句を言われたり勝手に修正されるのも癪なのでeslintとprettierは入れない。

$ yarn create nuxt-app portfolio
? Project name portfolio
? Project description tetsugi's portfolio
? Use a custom server framework none
? Use a custom UI framework vuetify
? Choose rendering mode Single Page App
? Use axios module no
? Use eslint no
? Use prettier no
? Author name tetsugi
? Choose a package manager npm

PWA化

PWA用のモジュールをインストールする。
導入手順はドキュメントに書いてある。

$ npm i -S @nuxtjs/pwa

nuxt.config.jsに追記。

module.exports = {
  /* 省略 */
  modules: [
    '@nuxtjs/pwa'
  ],
  manifest: {
    name: "tetsugi's portfolio",
    lang: 'ja'
  },
  /* 省略 */
}

.gitignoresw.*を追記。
また、アイコンとする画像をstatic/icon.pngに配置する。512 * 512以上を推奨。

デザインする

とりあえず次の項目を入れることにした。

  • ジャンボトロン・メニュー
  • 自己紹介
  • スキル
  • 作ったもの一覧
  • コンタクト

後で自分が変更しやすいよう、各パーツはコンポーネントとして分離することにする。
以下、少し考えた部分だけまとめる。

ジャンボトロン

Vuetifyのv-jumbotronは非推奨になったようなので、代わりにv-imgv-responsiveを組み合わせて使う。
v-imggradient属性で軽くグラデーションをつけるとそれっぽく見える気がする。

文字やボタンが中央揃えになるようにalign-centertext-xs-centerをつける。
Google Fontsから気に入ったフォントを選んで、タイトルに設定すると見栄えがよくなるかも。
ボタンには該当IDの要素までスクロールする処理を持たせた。

<template>
  <v-img 
    src="/img/jumbotron.jpg"
    max-height="320px" 
    gradient="to top right, rgba(63,81,181, .4), rgba(25,32,72, .4)">

    <v-container fill-height>
      <v-layout align-center>
        <v-flex text-xs-center>
          <h3 class="display-3 white--text">
            <span class="jumbotron-title">Tetsugi's Portfolio</span>
          </h3>

          <div class="mt-4">
            <v-btn @click="$vuetify.goTo('#profile', options)">PROFILE</v-btn>
            <v-btn @click="$vuetify.goTo('#skills', options)">SKILLS</v-btn>
            <v-btn @click="$vuetify.goTo('#works', options)">WORKS</v-btn>
            <v-btn @click="$vuetify.goTo('#contact', options)">CONTACT</v-btn>
          </div>
        </v-flex>
      </v-layout>
    </v-container>
  </v-img>
</template>

<script>
export default {
  data() {
    return {
      options: {
        duration: 700,
        offset: 0,
        easing: 'easeOutCubic'
      }
    }
  }
}
</script>

<style scoped>
.jumbotron-title {
  font-family: 'Orbitron', sans-serif !important;
  border-bottom: solid 1px white;
}
</style>

スキルについて書くカード

以下のようにすると各スキルの説明や評価を修正しやすいと思った。

<skill
  title="言語などの名前"
  color="blue"
  :rating="3">

  <template slot="text">
    説明
  </template>

  <template slot="list">
    <skill-list-item 
      name="その言語などに関わりが深いフレームワークなどの名前" 
      :rating="2">
      説明
    </skill-list-item>
  </template>
</skill>

たとえばJavaScriptなら、slot="text"のところにJavaScriptの使用歴や感想を書き、skill-list-itemにVue.jsやReactがどの程度いじれるか書いていく。
コンポーネントとして切り出しているので、デザインが気に食わなくなったらSkill.vueSkillListItem.vueを変更すればすぐに見た目を変えられる。
あまり変な共通化をすると罠になるが、今回は小さいプロダクトなので便利になればそれでいい。

フローティングボタン

各項目にスクロールするメニューが上部についているため、一番上にスクロールできるフローティングボタンをつけたくなった。
ジャンボトロンのmax-height320pxにしたので、300pxほどスクロールしたら一番上に戻るボタンを右下に常に表示することにする。
右下固定はfixed bottom right属性を付与すれば実現できる。
スクロールに追従して一番上からのオフセットを状態として保持し、computed300pxを超えているかどうかを返せば、v-showで表示非表示を切換できそうだ。

スクロールのアニメーションはジャンボトロンと同じものを使いたかったので、ジャンボトロンがあるindex.vueの適当な箇所に次のコードを追記した。 スクロールを検知して処理を呼び出すため、適当な要素の属性にv-scroll="onScroll"を追加した。

<template>
  <v-fab-transition>
    <v-btn
      fixed
      dark
      fab
      bottom
      right
      color="pink"
      v-show="showFloating"
      @click="$vuetify.goTo(0, options)">

      <v-icon>keyboard_arrow_up</v-icon>
    </v-btn>
  </v-fab-transition>
</template>

<script>
export default {
  data() {
    return {
      offsetTop: 0,
    }
  },
  computed: {
    showFloating() {
      return this.offsetTop >= 300
    }
  },
  methods: {
    onScroll(e) {
      this.offsetTop = document.documentElement.scrollTop || document.body.scrollTop
    }
  }
}
</script>

デプロイ

GitHub Pagesのユーザーページとしてポートフォリオサイトを公開したい。
ついでに自動でデプロイビルドするようにして欲しい。
Nuxt公式GitHub Pagesにデプロイする手順が載っているが、これではリポジトリ用のページになってしまう。

少し考えた結果、developブランチに成果物をコミットし、masterにデプロイすることにした。
残念ながら、ユーザーページのリポジトリではTravis CIで自動ビルドデプロイすることはできないようだ。

push-dirというツールをインストールする。
distbuildディレクトリを別のブランチにプッシュできるイカしたツールだ。
GitHub Pagesではmastergh-pagesブランチにプッシュする必要があるため、力を発揮する。

$ npm i -D push-dir

package.jsonのnpm scriptsの部分を追記する。
--dirには対象とするディレクトリ、--branchにはプッシュ先のブランチ名を書く。

{
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "deploy": "push-dir --dir=dist --branch=master --cleanup",
    "gd": "npm run generate && npm run deploy"
  }
}

push-dirHTTPSでは疎通できずエラーを吐くのでSSHにしておく。これで少し詰んだ。
毎回パスワード入力が求められるのもアレなので、最初からSSHにしておくべき。

あとは更新したくなったらnpm run gdすればいい。楽。

感想

create-nuxt-appGitHub Pagesなどを使えば高速でWebページを作って無料でホスティングできる。
PWA化したので、AndroidChromeiOSSafariでホーム画面に追加することで、見せたい人にすぐに見せびらかせる。
慣れれば見栄えが良くて保守性も高いものをかなり速く作れそう。