自分のサークルの公式サイトをリファクタリングしようかなと思ったけど、どう考えても自分の力ではリファクタリングするくらいなら作り直したほうが良さそうなので、せっかくだから今勉強中のVue.jsを使って作り直したいと思う。サークルのあたりはぼかしていくよ。
前提条件
制作開始時点でのバージョン
- npm 6.14.10
- Vue-cli 4.5.10 (-> 4.5.11 update)
- vue-router@3.5.1
これらの導入に関してはすでに完了しているものとする。ここみてインストールできないならまだVue.jsを使える段階にないよ。
プロジェクト作成の前にvue-cliのアップデート実行
SHELL:
$ cd ~/Documents/my_site //プロジェクトを作成したいディレクトリに移動
my_site $ vue create mysite
Vue CLI v4.5.10
┌───────────────────────────────────────────┐
│ │
│ New version available 4.5.10 → 4.5.11 │ //<-新しいバージョンあるからそれ使えよ(意訳)
│ Run npm i -g @vue/cli to update! │
│ │
└───────────────────────────────────────────┘
? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 2] babel, eslint)
Default (Vue 3 Preview) ([Vue 3] babel, eslint)
Manually select features
^C //(Ctrl+C同時押し) 一旦終了
my_site $ npm i -g @vue/cli //言われた通りアップデートコマンドを実行
...cut...
my_site $ vue --version
@vue/cli 4.5.11
my_site $ vue create mysite
Vue CLI v4.5.11
? Please pick a preset: (Use arrow keys)
Default ([Vue 2] babel, eslint)
❯ Default (Vue 3 Preview) ([Vue 3] babel, eslint)
Manually select features
...Installing...
🎉 Successfully created project mysite.
👉 Get started with the following commands:
$ npm run serve
プロジェクトのローカルサーバを立ち上げてみる
SHELL:
my_site $ cd mysite //作成したプロジェクトのディレクトリに入るのを忘れずに!
mysite $ npm run serve
DONE Compiled successfully in 7610ms 2:29:59
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.0.6:8080/
Note that the development build is not optimized.
To create a production build, run npm run build.
とりあえずこれでブラウザに localhost:8080 を入力すればページが見られるようになっているはず。

できてますね。いいですね、素晴らしい。次行きましょう。
ディレクトリ構成の確認
ここで、GUIの方でディレクトリを確認してみる。

基本的にはこれのsrc内部をガリガリ書いていくことになる。publicのhtmlもたまに書き込んだりするが基本的にはそういうのがないように作るのが望ましいんじゃないかなって思うのは、まだまだ初心者だからだろうか。
ちなみにプロジェクトを公開するのはここにはまだないdistのフォルダ内のやつですね。ビルド(npm run build)すると生成されます。
vue-routerの導入
サイトは複数ページの構成にするつもりなので、vue-routerを導入する。これはnpmを使って入れるので、シェル使いまーす。
あ、公式ドキュメントはここです。ちゃんと読んでください。
やったけど無視する工程
これは意味なかったので無視して次のコマンドです。
SHELL:
^C //serverを一旦終了させる
mysite $ npm install vue-router
+ vue-router@3.5.1
これを実行する
こっちを使えってよく見たら書いてありましたね。
SHELL:
^C //(Ctrl+C同時押し) serverを一旦終了させる
mysite $ vue add router
WARN There are uncommitted changes in the current repository, it's recommended to commit or stash them first.
? Still proceed? Yes //回答する
📦 Installing @vue/cli-plugin-router...
+ @vue/cli-plugin-router@4.5.11
updated 1 package and audited 1326 packages in 9.655s
70 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
✔ Successfully installed plugin: @vue/cli-plugin-router
? Use history mode for router? (Requires proper server setup for index fallback
in production) Yes //回答する
🚀 Invoking generator for @vue/cli-plugin-router...
📦 Installing additional dependencies...
updated 1 package and audited 1325 packages in 7.785s
70 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
⚓ Running completion hooks...
✔ Successfully invoked generator for plugin: @vue/cli-plugin-router
vue add routerを実行すると自動的にページが書き換えられる
そのため、先ほどとはページが変わっていることがlocalhost:8080からも見て取れる

まずはページを増やす
今必要なページは以下の通り
- トップページ
- アバウトページ
- ブログ(お知らせ)ページ
- 作品ページ
- 連絡先ページ
まずはこのページができるようにしていく。
ルーティングはsrc/router/index.jsが担っているのでまずはそれを開いた上で、過去記事からやり方を引っ張ってきたいと思う。
router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home,
meta: { title: 'サークル公式サイト' }
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
meta: { title: 'サークルとは' }
},
{
path: '/blog',
name: 'Blog',
component: () => import(/* webpackChunkName: "Blog" */ '../views/Blog.vue'),
meta: { title: 'おしらせ' }
},
{
path: '/works',
name: 'Works',
component: () => import(/* webpackChunkName: "Works" */ '../views/Works.vue'),
meta: { title: '作品の紹介' }
},
{
path: '/contact',
name: 'Contact',
component: () => import(/* webpackChunkName: "Contact" */ '../views/Contact.vue'),
meta: { title: 'お問い合わせ' }
}
]
const DEFAULT_TITLE = 'サークル公式サイト'
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.afterEach((to) => {
document.title = to.meta.title || DEFAULT_TITLE
})
export default router
一部文言はぼかしてるけど全文です。これで、<title>の中身もバッチリです。
ちなみにこの段階だとSHELLでエラーを吐いてる
SHELL:
ERROR Failed to compile with 3 errors 3:14:59
These relative modules were not found:
* ../views/Blog.vue in ./src/router/index.js
* ../views/Contact.vue in ./src/router/index.js
* ../views/Works.vue in ./src/router/index.js
つまるところ、ページを追加したけど、そのコンポーネントがないですがどうして……っていうお知らせなので、今度はこれを追加していきます。とりあえずエラーが消えないといろいろ確認ができないので、viewsディレクトリの中に最初からあるHome.vueをコピペして名前を変えます。

これでエラーは消えたはずです。
増えたページが動いているかを確認する
確認するにはAbout.vueが参考になるので、そのコードをHome.vue以外の全てに適用する。

次に、これらのページにアクセスできるよう、App.vueのコードに追記する。
App.vue:
<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
<router-link to="/blog">Blog</router-link>
<router-link to="/works">Works</router-link>
<router-link to="/contact">Contact</router-link>
</div>
<router-view/>
</template>
この段階でエラーが出ていなければ、もう閲覧できるようになっているはずだ。


動いていることが確認できました。
共通のヘッダとフッタを作成する
どのページも同じヘッダとフッタを用意するのは決まっているので、とりあえず全ページでそれが表示できるようにする。
ヘッダ用のコンポーネントを作成する
componentフォルダの中にHelloWorld.vueがあるのでそれ一旦コピペして名前をHeaderItem.vueなんて感じにします。※ここでheader.vueとかにするとかなり面倒なことになるので、2語をくっつけた感じにしましょう。
HeaderItem.vue:
<template>
<header>
<p>This is Header Area</p>
</header>
</template>
<script>
export default {
name: 'HeaderItem',
props: {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
header {
background-color: #224343;
color: #efefef;
}
</style>
ひとまずこんなもんでいいでしょう。あとはこれを確認するための表示部分のコードを書きます。
共通部などのコードはApp.vueに書きます。
App.vue:
<template>
<HeaderItem />
<router-view />
</template>
<script>
import HeaderItem from '@/components/HeaderItem.vue'
export default {
name: 'app',
components : {
HeaderItem
}
}
</script>
...以下省略...
エラーが出ていなければ、localhost:8080で更新されたページが見えているはずです。

同様にフッタのコンポーネントも作成する
FooterItem.vue:
<template>
<footer>
<p>This is Footer Area</p>
</footer>
</template>
<script>
export default {
name: 'FooterItem',
props: {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
footer {
background-color: #224343;
color: #efefef;
}
</style>
App.vueにも加筆する
App.vue:
<template>
<HeaderItem />
<router-view />
<FooterItem />
</template>
<script>
import HeaderItem from '@/components/HeaderItem.vue'
import FooterItem from '@/components/FooterItem.vue'
export default {
name: 'app',
components : {
HeaderItem,
FooterItem
}
}
</script>
...以下省略...
エラーが出てなければOK。

あとはそれぞれの部品を作っていくだけ
作りかけだったHeaderItem, FooterItemとviewsディレクトリにある全ファイルを書き換えれば基本的に完成となります。とはいえ、リンクの貼り方とかがちょっと変わってるのでそこだけ紹介する。
HeaderItem.vue:
<template>
<header>
<nav>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-link to="/blog">Blog</router-link>
<router-link to="/works">Works</router-link>
<router-link to="/contact">Contact</router-link>
</nav>
</header>
</template>
リンクは全てrouter-linkとして、title属性なんかも使えたはず。展開されると普通のaタグになるので、CSSはaタグ指定で効いてくれる。
完成したらビルドしよう
一通りエラーもなく、満足いくサイトに出来上がったら、ビルドをして、公開できるコードを生成する。Shellのserveを一旦止めて以下のコードを打ち込むだけでいい。
SHELL:
^C //(Ctrl+C同時押し)
mysite $ npm run build
DONE Compiled successfully in 11529ms 4:27:07
File Size Gzipped
dist/js/chunk-vendors.e5df94c0.js 102.49 KiB 37.93 KiB
dist/js/app.5d14c712.js 7.78 KiB 2.84 KiB
dist/js/Contact.dc2ce5ef.js 0.35 KiB 0.27 KiB
dist/js/Works.21a082c2.js 0.34 KiB 0.27 KiB
dist/js/about.741f1cf6.js 0.34 KiB 0.26 KiB
dist/js/Blog.bc5e87e7.js 0.34 KiB 0.26 KiB
dist/css/app.1f06c19f.css 0.71 KiB 0.37 KiB
Images and other types of assets omitted.
DONE Build complete. The dist directory is ready to be deployed.
INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
あとはdistフォルダの中身をそっくりサーバにあげれば公開完了です。お疲れ様でした。

おわりに
まだ作り終わってないので細かいところはこれから詰めるので、今後加筆修正するかもです。
っていうかね、やりながら記録しながらこっち書きながらでめっちゃ疲れた。夜中だよこれ書いてるの……