あらすじ
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:文法があっているかはわかりません