VuePress: VuePressでブログをつくるためのTips

ブログ(このサイト)を「WordPress + レンタルサーバー」から「VuePress + Netlify」に移行した。これにより、

  • 記事本文をgitで管理できる。
  • 維持費がドメイン代のみ。

というゴキゲンな運用を実現している。備忘をかねてブログ制作にあたって調べたことをここにまとめておく。

※本稿はVuePress 1.3.1時点の情報です。

※[2020/6/17 追記] 本サイトはVuepressからGatsby.jsに移行しました。

「VuePressで自作テーマ作ってブログやりてーな」という場合に気になるであろうアレコレ

本サイト自体がVuePress + Netlifyのみで構築しているので、ここで実現できていることはすべて可能。なお、公式のブログ用プラグインは使っていない。サイト作成時はまだβ版だったのでスルーした。

テーマ編集

Vue.jsの知識さえあればとくに悩まずカスタマイズできると思う。本サイトはゼロベースでテーマを作成しているが、「設定中のテーマをエクスポートして編集」という手もある。その場合はvuepress ejectで設定中のテーマをエクスポートして編集すればOK。

スタイル

stylusを標準装備している。

TypeScript

非対応。今後に期待。

投稿

Markdownで書くので、テーマやconfig類と一緒にgit管理できる。テーマ内の<Contents />で描画される。

タイトルや投稿日、メタ情報はFront Matterで定義する。

---
title: タイトル
date: 2020-01-01
description: ディスクリプション
---

# Hello VuePress

固定ページ

WordPressでいう固定ページのような概念は存在しない。投稿と何らかの区別が必要な場合はFront Matterで判別する。

例)Front Matterでhomeを定義し、値に応じてレイアウトを変える。

---
home: true
---

# Hello VuePress
<template>
  <div>
    <Home v-if="$page.frontmatter.home" />
    <Page v-else />
  </div>
</template>

カテゴリー/タグ

可能。Front Matterで定義する。

---
title: Hello VuePress
date: 2020-01-01
category: hoge
---

# Hello VuePress
computed: {
  posts() {
    // categoryがhogeの記事を日付の降順で取得する
    return this.$site.pages
      .filter(page => page.frontmatter.category == 'hoge')
      .sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date));
  }
}

ただの値なので、どう使うかはテーマ次第。自作テーマなら別に「category」という名前にしなくてもいい。

タグも同様で、以下の記法でArrayにできるというだけ。

---
title: Hello VuePress
date: 2020-01-01
tags:
  - hoge
  - fuga
---

カテゴリー/タグそのものの一覧は、ゴリゴリ書くしかなさそう。私はいらなかったので深追いしていない。vuepress-plugin-blogを使えばthis.$categories.listって感じで取得できるらしい。

投稿の公開日/更新日

デフォルトテーマではコミット日時が表示される模様。自作ならFront Matterで定義した日付を表示することもできる。

---
title: Hello VuePress
date: 2020-01-01
---
import { formatDate } from '../util'

export default {
  computed: {
    date () {
      return formatDate(this.$page.frontmatter.date)
    }
  }
}
export function formatDate(date) {
  var dateObj = new Date(date)
  return "yyyy/MM/dd"
    .replace(/yyyy/g, dateObj.getFullYear())
    .replace(/MM/g, ('0' + (dateObj.getMonth() + 1)).slice(-2))
    .replace(/dd/g, ('0' + dateObj.getDate()).slice(-2))
}

見出しのアンカーを消す

.mdに書いた見出し(h1、h2など)にはデフォルトでアンカーが付く。付けたくない場合はconfig.jsで表示有無を切り替えられる。

module.exports = {
  markdown: {
    anchor: { permalink: false }
  }
}

.md内の改行をbrタグで出力する

デフォルトでは改行を無視されてしまう。改行をbrタグにしたい場合はconfig.jsで設定する。

module.exports = {
  markdown: {
    extendMarkdown: md => {
      md.set({ breaks: true })
    }
  }
}

パーマリンク

デフォルトでは.mdのディレクトリ階層にもとづいたパーマリンクになる。変更したい場合はFront Matterで定義する。

---
title: Hello VuePress
date: 2020-01-01
permalink: /hoge
---

# Hello VuePress

Googleアナリティクス

プラグインを入れてIDだけ設定すればOK。公式サイトに手順が載っている。
Google Analytics Plugin | VuePress

Googleアドセンス

Githubにサードパーティのプラグインも転がっていたが、私は使っていない。普通にコンポーネントをつくればいいだけなので、自作の方が好都合だった。

検証と本番での切替はprocess.env.NODE_ENVで判定するのがお勧め。

  • 検証(devコマンドでの実行時):development
  • 本番(buildコマンドでの生成時):production
<template>
  <aside>
    <template v-if="adtest">
      <!-- 検証用のコード -->
    </template>
    <template v-else>
      <!-- 本番用のコード -->
    </template>
  </aside>
</template>

<script>
export default {
  computed: {
    adtest () {
      return process.env.NODE_ENV == 'development'
    }
  }
}
</script>

sitemap.xml

デフォルトでsitemap.xmlを生成してくれる機能はない。私はサードパーティのプラグインを使うことにした。
GitHub - ekoeryanto/vuepress-plugin-sitemap: Sitemap generator plugin for vuepress.

画像などの静的ファイル

.vuepress/public配下に置く。

例)
public/hoge.png → https://example.com/hoge.png
public/images/hoge.png → https://example.com/images/hoge.png

外部参照(jQueryとかGoogleフォントとかCDNなど使うとき)

config.jsで外部参照を指定できる。

module.exports = {
  head: [
    ['link', { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap' }],
    ['script', { src: 'https://code.jquery.com/jquery-3.4.0.min.js' }]
  ],
}

headタグ内にいい感じに挿入してくれる。bodyタグの中でよければテーマ内でも書けるが、とくに事情がなければこれが無難だと思う。

テーマ内でconfig.jsの値を取得

module.exports = {
  themeConfig: {
    hoge: 'ほげぇ'
  },
this.$themeLocaleConfig.hoge

テーマ内でFront Matterの値を取得

---
hoge: ほげぇ
---

# Hello VuePress
this.$page.frontmatter.hoge

シンタックスハイライト

デフォルトでPrism.jsが使える。記法は公式ドキュメントに記載あり。
Markdown Extensions | VuePress

テーマを自作する場合はデフォルトテーマに含まれているcode.stylを取り込むといい感じに使える。もちろんスタイルごと自作してもいい。

MathJax

デフォルトでは非対応だが、公式プラグインをインストールすれば簡単に使える。
GitHub - vuepress/vuepress-plugin-mathjax: Use TeX in VuePress.

↓こんな感じ。

E=mc2E=mc^2

あとがき

静的サイトジェネレーターは僕たちをDBから解放してくれる。gitですべてを管理でき、アプリケーションサーバーを必要としない。CMSよりもずいぶん気楽に運営できる。

しかしこれはデメリットでもあって、現時点ではエンジニアしか使えないと思った方がいい。記事を書くにもgitやnode.jsが必要なのでコマンドアレルギーを持つ人には敷居が高く、WordPressのように記事の書き方だけ教えればOKとはいかない。いずれCMSのようなUIをもつ静的サイトジェネレータ―が現れれば、受託開発などで使える可能性も出てくるかもしれない。

ともあれエンジニアがブログのような「ドキュメント主体で、更新頻度が少ないサイト」を運営するのであれば、静的サイトジェネレータ―は有力な選択肢だろう。