# GitHub Pagesでポートフォリオサイトを公開したときの話

## はじめに
(これは12/5のMIS.W55代非公式アドカレの記事です。)
こんにちは。[すい(@828sui)](https://twitter.com/828sui)です💤
この前[自分のポートフォリオサイト](https://sui828.github.io/)を更新するついでにデザインを一新しました。
改修にあたって、Vue.jsというJavaScriptのフレームワークを使いました。
## Vue.jsのざっくりした説明
**Webアプリケーション、WebサイトのUI部分の開発を手助けしてくれるツール**です。
HTMLに似た文法なので、HTMLを手打ちして個人ページを制作した経験がある人にはとっつきやすい&未経験者でもなんとなくで始められるのが良い点だと思います。
さらに他のライブラリを使って機能を拡張することもできるので、自力で実装が難しそうなところでもある程度はなんとかなってしまうのも良いです。今回はUIデザインをもっと楽に・きれいにするためにVuetifyというライブラリを導入しています。
## コードを書く
今回**SPA**(single-page application)といって、サイトの読み込みを最初にまとめて行うことでページ遷移時などの再読み込みがいらないようにページを制作しました。
ざっくり説明すると、index.htmlの`<head>`タグの中に置いたJavaScriptによってページの表示を行い、ボタンをクリックするたびにページの中身とURLを書き換えるみたいなことをしています。なので、HTMLファイルは最低限index.htmlファイルだけでいいということになります。

中身の部分はvueファイルに記述していきます。例えばトップページのHTML部分はこんな感じ。
```
<template>
<div class="top">
<div class="zodiac-trajectory-svg">
<ZodiacTrajectory />
</div>
<div class="top-icon">
<v-btn icon class="top-icon-about" to="/im3py_/about"><IconAbout /></v-btn>
<v-btn icon class="top-icon-news" to="/im3py_/news"><IconNews /></v-btn>
<v-btn icon class="top-icon-picture" to="/im3py_/picture"><IconPicture /></v-btn>
<v-btn icon class="top-icon-music" to="/im3py_/music"><IconMusic /></v-btn>
<v-btn icon class="top-icon-novel" to="/im3py_/novel"><IconNovel /></v-btn>
<v-btn icon class="top-icon-others" to="/im3py_/others"><IconOthers /></v-btn>
</div>
<p class="top-text-about">About</p>
<p class="top-text-news">News</p>
<p class="top-text-picture">Picture</p>
<p class="top-text-music">Music</p>
<p class="top-text-novel">Novel</p>
<p class="top-text-others">Others</p>
</div>
</template>
```
`<div>`とか`<p>`とかはHTMLタグですね。
`<v-btn>`タグはVuetifyで新しく追加した、ボタンを表示させるためのタグになります。
また、`<ZodiacTrajectory />`や`<Icon*** />`の類は、svgファイルをインポートしてきてタグのような形でページに差し込んでいるものになります。
感覚としてはタグの種類が増えたHTMLを書いている感じです。
Vuetifyを導入する強みとしては、上のようにボタンやテキストボックスなどを**タグ1つで簡単に作れるようにしてくれる**ところと、**画面サイズによる細かい配置の違いを楽に実装できるところ**にあります。
例えばPictureページでは、スマホ程度の画面サイズだと作品が1列に2つ、タブレット程度だと3つ、PC程度だと4つ表示するようにしています。
```
<template>
<div class="works">
<v-row>
<v-col cols="6" sm="4" md="4" lg="4" xl="3" xxl="3" v-for="(item, i) in musics" :key="i" class="works-list">
<v-card color="#032a57" height="90%" class="links" :href="item.link" target="_blank">
<v-img :src="item.src"></v-img>
<v-card-title class="works-list-title">{{
item.title
}}</v-card-title>
<v-card-text class="works-list-description">{{
item.description
}}</v-card-text>
</v-card>
</v-col>
</v-row>
</div>
</template>
```
上の`v-col`タグでは、画面の幅を12等分して、要素の幅をそのうち何個分にするかを指定しています。(グリッドシステムとかレスポンシブデザインとかで調べると詳しく解説している記事が出てくると思います。)
タグの中のオプションとして、画面サイズがsmのとき、mdのとき、…と条件分岐して指定することができるので、CSSでわざわざ書かなくても1行で済んでしまうのがとても楽で助かっています。
## ビルドする
Vue.jsやVuetifyで追加したタグをHTMLに変換するためにビルドをします。
ビルドしたものは`docs`フォルダか`dist`フォルダに格納されると思います(設定による)。
これをローカル環境で開くと...

真っ白のページが出てきます。ブックマークバーが汚いのは気にしないでください。
これはビルドが成功してもこうなります。大丈夫です。
これを自前のサーバーにアップロードして公開すると、なぜかちゃんと表示できます。表示できないときは`vue.config.js`の設定をいい感じに直すといいかもしれません。
## GitHub Pagesで公開する
GitHubでパブリックリポジトリにビルドしたものを入れてPagesの設定をすると、自前でサーバーを調達することなくサイトを公開できます。
このとき、トップページはうまく表示できるかもしれませんが、それ以外のページを表示しているときにURLを更新したり、URLを手打ちしたりすると404エラーページに飛ばされます。
これは、URLをHTMLファイルの場所と解釈したときにファイルが存在しないせいで発生しています。
なので、一旦index.htmlに送って、そこの**JavaScriptにURLを解釈してもらう**という処理が必要となります。

自前のサーバーの場合は`.htaccess`で処理を行い、GitHub Pagesの場合はエラーページをカスタムすることで行います。
新たに404.htmlを作成し、そこに以下のような処理を追加します。
```
<script>
let l = window.location;
let p = 'https://sui828.github.io/?p=' + l.pathname.substr(1);
l.replace(p)
</script>
```
これでURLの`github.io/`以降の部分をクエリとして扱い、トップページに遷移させています。
また、トップページのスクリプト部分で、クエリを元に戻してページの中身を更新する処理を入れるとうまく動きます。
```
<script>
export default {
methods: {
QueryIs: function(){
if(this.$route.query.p !== undefined){
this.$router.push('/' + this.$route.query.p)
}
},
},
mounted(){
this.QueryIs();
},
};
</script>
```
`methods`や`mounted()`については解説しませんが、JavaScriptの処理をいい感じのタイミングでできるようにしてくれるものです。(ライフサイクルで調べるといいかもしれませんが、正直わたしもよく分かっていないので知らなくてもなんとかなります。)
## いかがでしたか?
HTMLとCSSの知識は一応いるのですが、Vue.jsを使ってもっと楽にWebページを制作できることが分かったかと思います。
皆さんもVue.jsを触ってみてください。ウチもやったんだからさ。
最後に、Twitterのフォローとniconico・YouTubeのチャンネル登録をお願いします。
普段は絵を描いたり曲を作ったり動画を作ったりしています。すいです。よろしくおねがいします。
[Twitter](https://twitter.com/828sui)
[niconico](https://www.nicovideo.jp/user/116019505)
[YouTube](https://www.youtube.com/channel/UC7ODCByUzHSCc_wYDhUWlFg)
[生成物置き場](https://sui828.github.io/)
明日はショコラ丸さんの記事です。ほなな~
これは最近描いた絵。
