あらすじ
VuePress の default theme が美しいのでこれで Blog を書きたいと思いました。
VuePress とは
コンセプトは以下2点です。
- Vue component を使用した Theme を扱う最小構成の静的サイトジェネレーター
- 技術的な文章を書くために最適化された default theme を提供する
一度読み込まれたHTMLは、それ以降 Single Page Application のように振る舞うためレンダリングは高速ですが、最初のHTMLにコンテンツを書き出しているので SEO との親和性も高い CMS です。
この振る舞いは nuxt generate と gatsby build と非常に良く似ています。
使われている技術と似ているサービス
Vue, Vue Router, webpack が使用されています。
VuePress を使ってドキュメントを書く
VuePress を Default Theme を使って利用する場合、必要な作業は以下の通りです。
- defaultTheme の振る舞いを
.vuepress/config.jsで設定します。 - Markdown 形式のテキストファイルを追加します。
Blog 化するために必要な事
VuePress を初期状態で使う場合、ナビゲーションの機能が不十分です。今回私が VuePress を Blog 向けに使う為に、以下の2点の作業を行いました。
- BlogIndexPage を追加し、記事一覧を表示する
- sidenav に各記事へのリンクを動的に生成する
BlogIndexPage を追加
.vuepress/components/PostIndex.vue を追加します。
<template>
<div>
<div v-for="post in posts">
<h3>{{ post.frontmatter.title }}</h3>
<p>{{ post.frontmatter.description }}</p>
<p><router-link :to="post.path">Read more</router-link></p>
</div>
</div>
</template>
<script>
export default {
computed: {
posts() {
return this.$site.pages
.filter(x => x.path.startsWith('/posts/') && !x.frontmatter.post_index)
.sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date));
}
}
}
</script>
現状だと Default Theme の Header や Sidebar などを override しづらい構成になっています。 自由にカスタマイズすることも可能なのですが eject する必要があります。まだ VuePress が alpha 版ということもあるので Theme に対するカスタマイズは避けたほうが賢明かもしれません。
ただし、上記のように Page 内に新たに Component を追加する場合は割と簡単です。
追加した PostIndex component を利用して記事一覧ページを作成するには /posts/README.md を以下のようにすればOKです。この例では記事一覧ページの幅を広げたいので pageClass を指定しています。 指定した class の CSS は.vuepress/styles/index.styl に記述をすれば適用できます。
--- post_index: true pageClass: post-index sidebar: false --- <PostIndex />
Sidebar を Blog 風にカスタマイズする
.vuepress/config.js に以下のように記述をすると Sidebar のカスタマイズが可能です。ただし Blog の Post のように何度も記事が追加される場合、都度このようにハードコーディングを行うのは煩雑です。
module.exports = {
themeConfig: {
sidebar: [
{
title: '2018',
children: ['/posts/2018/xxxx', '/posts/2018/yyyy']
},
{
title: '2017',
children: ['/posts/2017/xxxx', '/posts/2017/yyyy']
}
]
}
}
Life Cycle の中で ready 関数が Hook されているので config を動的に変更することができます。私は年ごとに記事をまとめたかったので以下のようにしました。
module.exports = (options, ctx) => {
return {
ready() {
const { pages, themeConfig } = options
const items = _.orderBy(pages, 'frontmatter.date').reverse()
const sidebar = []
const posts = items.filter(p => p.frontmatter.title && p.frontmatter.type !== 'talk')
for (let i = 0; i < posts.length; i++) {
const post = posts[i]
const m = moment(post.date)
const year = m.year()
if (!sidebar[year]) {
sidebar[year] = []
}
sidebar[year].push(post.path)
}
const years = Object.keys(sidebar)
themeConfig.sidebar = years.sort().reverse().map(year => {
return {
title: year,
children: sidebar[year].map(item => item)
}
})
}
}
}
まとめ
というわけで Default Theme に少しだけ Component を追加していますが、このようにして Blog 風にカスタマイズすることができました。VuePress は非常に美しいデザインで、技術的なドキュメントを作成するのにぴったりだと思います。
以下、VuePress を使った私の Blog です。海外進出を目論んでいるので英語で書いていますが*1 VuePress で書き出されているのでよかったらご覧になってください。
Blog: https://okamuuu.com/
ソースコード: https://github.com/okamuuu/okamuuu.com
*1:文法があっているかはわかりません