RACCOON TECH BLOG

株式会社ラクーンホールディングス 技術戦略部より、
tipsやノウハウなど技術的な話題を
発信いたします。

VuePressの使い方!記事一覧と前後投稿リンク付きブログの作成方法

こんにちは。
2018年度新卒で開発チーム所属の川崎です。
今回はVuePressを使って、記事一覧と前後投稿リンク付きのブログサイトを作成してみましょう。
VuePressはVue.jsが使えるなら学習コストが低く、カスタマイズしやすい静的サイトジェネレータです。

サイトの公開にはFirebase Hostingを利用します。

はじめに

静的サイトジェネレータとは

サイトの共通部分(ヘッダーやサイドバーなど)を自動的に自分が作成したページと結合して、HTMLやJavaScript、CSSといった静的コンテンツとして出力するライブラリ・フレームワークのことを指します。
公開にアプリケーションサーバを必要とせず、HTTPサーバのみでサイトを公開できるというメリットがあります。
現在静的サイトジェネレータは数多く存在します。

そのなかでも今回はVue.jsが使えるVuePressという私おすすめの静的サイトジェネレータを使いたいと思います。

VuePressとは

2018年4月にVueの作者Evan You氏(github)が作成したvue.jsを使った静的サイトジェネレータです。
同じくVue.jsを使っている静的サイトジェネレータにはnuxt.jsがあります。こちらは自分でMarkdownをHTMLに変換するライブラリを導入しなければMarkdownでページを書くことはできません。
しかしVuePressでは標準でページコンテンツをMarkdownで記述することができ、Markdownファイル内部にVueコンポーネントを配置できるという特徴があります。

Firebaseとは

googleが公開しているクラウドサービスのひとつです。
そのなかでも今回はwebサイトのホスティングサービスであるFirebase Hostingを利用します。
github pagesやnetlifyを使いたい方は各自で読み換えていただけると幸いです。

VuePress開発環境のセットアップ

ブログを作り始める前に、VuePressでサイトを作る環境をセットアップします。
VuePressを導入して、サイトのトップページを作成しましょう。
※今回はnode.js(執筆時v8.11.2)yarn(執筆時v1.9.4)がインストールされている前提でお話します。

$ cd ./ブログを配置するディレクトリ
# npmでもインストール可能ですが、2018年9月現在公式でyarnを用いたインストールが推奨されています。
$ yarn global add vuepress
# VuePressでは各ディレクトリのREADME.mdがindex.htmlに変換されます。
$ touch README.md
# vuepress用のconfigファイルを作成します。
$ mkdir .vuepress
$ touch .vuepress/config.js

configファイルは以下のように記述します。

// .vuepress/config.js
module.exports = {
    title: 'テストブログ',
    description: 'これはテストブログの説明です。'
}

README.mdの中身はこのようしましょう。

---
home: true
---
## トップページです。
この画面はトップページです。

それではサーバを立ち上げてみましょう。

# 開発サーバーを立ち上げるコマンド
$ vuepress dev

これでローカルでサーバが起動しました。
早速http://localhost:8080にアクセスしてみましょう。

このように表示されれば成功で、セットアップ完了です。
あとはプロジェクトディレクトリ以下にブログ記事をMarkdownファイルとして作成すれば、VuePressがHTMLファイルに変換してくれます。
この時点でFirebase Hostingにデプロイしても問題ないですが、現状だとトップページしか存在しません。
なので次の項からはMarkdwonでブログ記事を書いてみて、更に独自の機能を実装してみようと思います。

ブログ記事の書き方について

ブログの記事はblogディレクトリを作成して、そこ保存していくことにします。

$ mkdir blog
$ touch blog/test.md

そしてblog/test.mdの中身をこのように変更します。
front-matterを使ってメタ情報を付与することができるので活用してみましょう。
dateには編集日付を記入してください。

---
title: テスト投稿1です。
date: yyyy-MM-dd
description: 記事の要約
---
# テスト投稿1
こんばんわ  
aa

これでhttp://localhost:8080/blog/test.htmlにアクセスすれば先ほど作成したブログ記事が表示されるようになります。
また、front-matterで設定したtilteがheadのtitleタグに設定されているはずです。
ブログ記事自体は完成しましたが、サイトのトップページに先ほど作成したブログ記事のリンクは存在しません。
そこでブログ記事一覧を表示するためのコンポーネントを作成し、ブログのトップページ(最初に作成したREADME.md)に動的なブログ投稿一覧を表示するようにしましょう。

ブログ記事の一覧を表示するコンポーネントの作成

$ mkdir .vuepress/components
$ touch .vuepress/components/PostList.vue

作成したPostList.vueを使って投稿記事一覧を表示するためのコードが以下になります。

// PostList.vue
<template>
    <div>
        <div v-for="post in posts">
            <h2><a v-bind:href="post.path">{{post.title}}</a></h2>
            <p>{{post.frontmatter.description}}</p>
            <a v-bind:href="post.path">続きを読む</a>
        </div>
    </div>
</template>
<script>
export default {
    computed: {
        posts() {
            return this.$site.pages
                // blogディレクトリ以下を投稿記事一覧表示の対象とする
                .filter(post => post.path.startsWith('/blog/'))
                // dateに設定した日付の降順にソートする
                .sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date));
        }
    }
}
</script>

コード15行目のthis.$site.pagesという変数にはサイトが表示できる全ページのメタ情報(PathやTitle)が配列として格納されています。参考:公式ドキュメント
front-matterで登録したdateもメタ情報の一部として参照できるので、それを基準にブログ記事を並べています。
そしてPostListコンポーネントを呼び出すために最初に作成したREADME.mdを以下のように変更します。

---
home: true
---

<PostList />

ここまでのステップを経た段階でこのように表示されていれば成功です。
これで投稿記事一覧がホームに表示されるようになりました。

次の記事、前の記事へのリンク作成

最後に、現在開いているブログ記事の次へ前へリンクを自動で生成する機能を作成しましょう。
これからサイトのテーマ部分のVueコンポーネントを編集するので、先ほどまで表示していたサイトのVueコンポーネントが格納されたファイル群を、ejectコマンドでプロジェクトディレクトリにコピーします。

$ vuepress eject

こうすることでテーマ部分のVueコンポーネントなどが.vuepress/theme上にコピーされます。
次にマークダウンを出力する部分のVueコンポーネントである.vuepress/theme/Page.vueファイルを編集し次へ前へリンクを生成する機能を付与します。
こちらでもサイトが表示できる全ページをもとに次のページと前のページを絞り込みます。
下記の内容をPage.vueファイルのcomputed内部に反映させてください。

    // 新規メソッド
    sortedPosts() {
      return this.$site.pages
          // blogディレクトリ以下のページを次へ前へリンク自動生成
          .filter(post => post.path.startsWith('/blog/'))
          // dateに設定した日付の降順にソートする
          .sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date))
    },
    // 新規メソッド
    pageIdx() {
      return this.sortedPosts
          .findIndex(page => page.path == this.$page.path)
    },

    // 既存のprev()メソッドに上書きしてください
    prev () {
      const prev = this.$page.frontmatter.prev
      if (prev === false) {
        return
      } else if (typeof prev === "undefined" && this.pageIdx > 0) {
        const prevPath = this.sortedPosts[this.pageIdx - 1].path
        return resolvePage(this.$site.pages, prevPath, this.$route.path)
      } else if (prev) {
        return resolvePage(this.$site.pages, prev, this.$route.path)
      } else {
        return resolvePrev(this.$page, this.sidebarItems)
      }
    },

    // 既存のnext()メソッドに上書きしてください
    next () {
      const next = this.$page.frontmatter.next
      if (next === false) {
        return
        // 最後より一つ前のページまで次へリンクを生成する
      } else if (typeof next === "undefined" && this.pageIdx < this.sortedPosts.length - 1) {
        const nextPath = this.sortedPosts[this.pageIdx + 1].path
        return resolvePage(this.$site.pages, nextPath, this.$route.path)
      } else if (next) {
        return resolvePage(this.$site.pages, next, this.$route.path)
      } else {
        return resolveNext(this.$page, this.sidebarItems)
      }
    },

それではサンプルのブログ記事を何本か追加してページを開いてみましょう。

上の画像のようになっていれば成功です。

Firebase hostingにアップロード

それではFirebaseにブログをアップロードしましょう。
まず、googleアカウントでログインしFirebaseコンソールにアクセスしプロジェクトを追加を押します。

次に以下のようなプロジェクトを作成します。

Firebase hostingにサイトをデプロイするにはfirebase-toolsが必要なので入れておきます。

$ npm install -g firebase-tools
$ firebase login
# プロジェクトのルートディレクトリで
$ firebase init
# Are you ready to proceed?
> yesと入力
# Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices. 
> Hostingを選択
# Select a default Firebase project for this directory
> 先ほど作成したプロジェクト名を選択
# What do you want to use as your public directory? (public)
> .vuepress/distと入力(ビルドして生成される公開用ファイル群は.vuepress/distに保存されるため)
# Configure as a single-page app (rewrite all urls to /index.html)?
> yesと入力

# プロジェクトのビルド
$ vuepress build
# Firebaseへのデプロイ
$ firebase deploy

これでFirebase上にブログが公開されました!お疲れ様でした。
早速アクセスしてみましょう。

おわりに

VuePressは強力なブログの作成支援機能がついているわけではないので、ポートフォリオサイト兼ブログという運用が個人レベルでは適していると思いました。
しかし公式githubのTodo Featuresにもブログサポートが挙がっているので、いずれブログ作成もやりやすくなるでしょう。
業務レベルでは会社で運用しているサービスの軽量ドキュメントとして使えるかもしれません。機会があれば弊社でも使ってみるように提案したいと思います。

関連記事

運営会社:株式会社ラクーンホールディングス(c)2000 RACCOON HOLDINGS, Inc