VuePressに移行した

2年半くらい前からずっとVue.jsを書いていましたが、最近になってVue開発チームから公式に静的サイトジェネレーターとしてVuePress[1]というプロダクトが公開されました。

私個人としてもNuxt.jsを使った静的SPAブログ用CMSを作っていたんですが、公式が出して今後も機能追加が継続的に見込めることからVuePressに移行することにしました。
VuePressの今後の機能追加の一つにブログ機能があるそうなのですが、現時点での標準ではまだまだなので今回は少しでもブログらしくカスタマイズした作業ログを残しておこうと思います。

VuePressを始める

今回のディレクトリ構成はこんな感じです。
この構成は以下の記事を参考にさせていただきました。
VuePressはコーダーの夢を見るか。 - Qiita

blog
├── package-lock.json
├── package.json
└── src
    ├── .vuepress       // VuePress関連の設定やコンポーネントを格納する
    │   ├── components
    │   ├── config.js
    │   ├── public
    │   └── theme       // vuepress eject .vuepressしたもの
    ├── 2018            // 記事を書く
    │   ├── 05
    │   └── index.md
    └── index.md        // Topページ
$ npm init

してpackage.jsonにvuepress dev src, vuepress build srcを追加します。

その後vuepress eject .vuepressをしてデフォルトテーマを取り出します。

注意

公式サイトにも書かれているのですがデフォルトテーマを取り出していろいろと編集をした場合、その後のデフォルトテーマの更新に追従していくのが面倒になるので注意してください。
(私のこの記事も更新するときに元に戻せるように書きました)

記事一覧ページを作る

トップページ及び各月のページに記事の一覧を出すようにしたいと思います。

VuePressでは各コンポーネントのthis.$siteに全記事の情報が含まれているので、そこから記事の情報を抜き出して記事名等を表示するようにします。

src/.vuepress/components/Articles.vueを作成して以下のように追加します。

<template>
<div>
  <div v-for="page in filteredPages" class="article-container" v-if="!page.frontmatter.exclude">
    <h3 class="article-title">
      <router-link :to="page.path">{{page.title || 'No Title'}}</router-link>
    </h3>
    <div class="tag-container">
      <i class="fas fa-tags tag-icon"></i>
      <div v-for="c in page.frontmatter.category" class="tag">{{c}}</div>
    </div>
    <div v-if="page.frontmatter.description" class="article-description">{{page.frontmatter.description}}</div>
  </div>
</div>
</template>

<script>
export default {
  name: 'Articles',
  props: ['pages', 'prefix'],
  computed: {
    filteredPages () {
      return this.pages.filter(page => page.path.includes(this.prefix || ''))
    }
  }
}
</script>

CSSは省略

そして記事一覧を出したいところで

## 記事一覧
<Articles :pages="this.$site.pages"/>
# 2018年の記事一覧
<Articles :pages="this.$site.pages" :prefix="this.$page.path" />

という風に書くとそのパス以下の記事の一覧が表示されるようになります。

サイドバーを右にする

サイドバーは右がいいなあと思ったので右にします。
モバイルの方は元のまま左から出すようにします。
以下は.vuepress/theme/styles内のファイルです。

theme.styl

.page
  padding-right $sidebarWidth // leftをrightに変更



.sidebar
  right 0  // leftをrightに変更
  border-right 1px solid $borderColor // 追加

mobile.styl

@media (max-width: $MQMobile)
  .page
    padding-right 0 // 追加

サイドバーにこれまでの月の記事一覧を表示する

util.jsにあるresolveSidebarItemsを以下に変更します。
type:'head'に対応する部分も追加しています。

export function resolveSidebarItems (page, route, site, localePath) {
  let pages = site.pages
  const list = []
  pages.forEach(pa => {
    const pathList = pa.path.split('/').filter(p => p !== '')
    console.log(pathList)
    let tmp = list
    let nowPath = ''
    let now
    pathList.forEach(name => {
      nowPath = nowPath + '/' + name
      now = tmp.find(e => e.path === nowPath)
      if (!now) {
        tmp.push({
          type: 'group',
          title: name,
          path: nowPath,
          collapsable: true,
          children: []
        })
        console.log(nowPath)
        now = tmp.find(e => e.path === nowPath)
        console.log(now)
      } 
      tmp = now.children
    })
  })
  console.log(list)
  return [page, {title: 'これまでの記事', type: 'head'}, ...list]
}


今回行った変更は以上です。
本当はカテゴリ別の記事一覧ページを作成したかったんですが、動的にページを生成する方法がわからなかったため今回は見送りとなりました。

また実現方法が見つかったら記事にしたいと思います。


  1. 公式サイト: https://vuepress.vuejs.org/ ↩︎