# Customize VuePress BLog

VuePressをBlog用にカスタマイズする手順を記す.

# Plugin

# @vuepress/plugin-blog

Blog用にするためのプラグインとして @vuepress/plugin-blog (opens new window)をインストールする. 多機能なプラグインでタグ・カテゴリ・記事一覧ページを作ったり,RSSを作ったり,サイトマップを作ったりできる.

なお,あくまでもプラグインなので〇〇ページを作る際に自分でレイアウトを作成する必要がある. レイアウトも一緒になった @vuepress/theme-blog (opens new window) もあるので面倒ならそっちを使ってもよさそう. あるいは 他のテーマ (opens new window) で気に入ったのがあればそれを導入して終了としてもいい.

ただテーマを導入するとカスタムがめちゃくちゃ大変になるので,最小構成で動かせる意味でもまずは @vuepress/plugin-blog のみの導入をおすすめ.

インストールはyarnで一発.

yarn add -D @vuepress/plugin-blog
1

またdocs/.vuepress/convig.jsで設定する.

const BASE_URL = "https://besolab.com";

module.exports = {
    plugins: [
        ['@vuepress/blog', {
            feed: { canonical_base: BASE_URL, },
            sitemap: {
                hostname: BASE_URL,
                changefreq: "weekly"
            },
            directories: [
                {
                    id: 'post',
                    dirname: '_posts',
                    path: '/',
                    itemPermalink: '/:year/:month/:day/:slug',
                },
            ],
            frontmatters: [
                {
                    id: 'category',
                    keys: ['category'],
                    path: '/category/',
                    layout: 'Categories',
                    scopeLayout: 'Category'
                },
                {
                    id: 'tag',
                    keys: ['tags'],
                    path: '/tag/',
                    layout: 'Tags',
                    scopeLayout: 'Tag'
                },
            ],
        }],
        ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

各オプション値 (feed, sitemap, directories, frontmatters) の意味は 公式のGettingStarted (opens new window) を見るのが良い.

更に,上記の設定で追加された下記5ページに対して,それぞれレイアウトを作成する(theme-blogをインストールした場合は不要).

  • 記事一覧ページ https://besolab.com/ に対応した docs/.vuepress/theme/layout/IndexPost.vue
  • タグ一覧ページ https://besolab.com/tag/ に対応した docs/.vuepress/theme/layout/Tags.vue
  • タグ個別ページ https://besolab.com/tag/vuepress (例) に対応した docs/.vuepress/theme/layout/Tag.vue
  • カテゴリ一覧ページ https://besolab.com/category/ に対応した docs/.vuepress/theme/layout/Categories.vue
  • カテゴリ個別ページ https://besolab.com/category/blog (例) に対応した docs/.vuepress/theme/layout/Category.vue

テーマを1個でも作るとデフォルトのものが読み込まれなくなるので,デフォルトテーマを抽出したのちに追加すること.

vuepress eject docs/
1

以下はサンプルで,記事情報$pagination.pages,カテゴリ情報$category,タグ情報$tagを利用してそれぞれのリストを表示している. 現在選択中のタグはリンクを張らないといったことがしたければ $currentTag.key を,カテゴリについてやりたければ $currentCategory.key を利用すると条件分岐ができる.

<template>
<div class="theme-container">
    <header>
        <!-- CategoryList -->
        <ul>
            <li v-for="t in Object.keys($category.map)">
                <a :href="'/category/' +  t">{{ t }}</a>
            </li>
        </ul>
        <!-- Tag List -->
        <ul>
            <li v-for="t in Object.keys($tag.map)">
                <a :href="'/tag/' +  t">{{ t }}</a>
            </li>
        </ul>
    </header>

    <!-- Post List -->
    <section class="post" v-for="p in posts">
        <h1><a :href="p.path">{{ p.title }}</a>

        <ul>
            <li>{{ p.display_date }}</li>
            <li><a :href="'/category/' + p.frontmatter.category">{{ p.frontmatter.category }}</a>
            <li v-for="t in p.frontmatter.tags">
                <a :href="'/tag/' +  t">{{ t }}</a>
            </li>
        </ul>
    </section>
</div>
</template>

<script>
export default {
    name: "IndexPost",

    computed: {
        posts() {
            const pages = this.$pagination.pages.map(v => {
                const { date, tags } = v.frontmatter;

                v.frontmatter.tags = tags.sort()

                function _pad(i, n, s = '0') {
                    return i.toString().padStart(n, s);
                }

                if (date) {
                    const t = new Date(date);
                    v.parsed_date = t

                    v.display_day = [
                        t.getFullYear(),
                        _pad(t.getMonth() + 1, 2),
                        _pad(t.getDate(), 2),
                    ].join('/')

                    v.display_time = [
                        _pad(t.getHours(), 2),
                        _pad(t.getMinutes(), 2),
                    ].join(':')

                    v.display_date = `${v.display_day} ${v.display_time}`
                }

                return v
            }).sort((b, a) => { return a.parsed_date - b.parsed_date });

            return pages
        },
    },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

上記でも最低限は動くがサイドバーやナビバーが消えるので,動作確認が済んだら docs/.vuepress/layouts/Layout.vue をコピペって改良するといい.

# @vuepress/google-analytics

https://vuepress.vuejs.org/plugin/official/plugin-google-analytics.html (opens new window)

グーグルのアクセス解析を設定するプラグイン. Google Analytics IDを取得するのが若干大変だが,VuePress設定としては値を入力するだけなので簡単

# Others

# GoogleSearch

グーグル検索に登録する際にサイト所有者確認とサイトマップが必要になる.

所有者確認方法は幾つか候補が用意されているが一番簡単なのはHTMLタグかと. 選択肢で選ぶとサイトのmeta情報に組み込む情報を教えてくれるので docs/.vuepress/config.js を以下のように弄ってデプロイする.

module.exports = {
    head: [
        ['meta', { name: "google-site-verification", content: "xxxxxxxxxx"}],
    ],
}
1
2
3
4
5

サイトマップはすでに@vuepress/plugin-blogで生成するようにしているので,聞かれたらそのパスを入力するだけでいい.

# fontawaresome

アイコン利用する際に便利なので導入する. いつの間にかユーザアカウント登録が必要になっていたので登録して,教えられたスクリプトを以下のように設定する.

module.exports = {
    head: [
        ['script', { src: "https://kit.fontawesome.com/xxxxxxxx.js", crossorigin: "anonymous"}],
    ],
}
1
2
3
4
5

あとは <i class="fas fa-tag"></i> といった形で利用できる. markdown中で頻繁に利用する場合はmarkdown-it-fontawesome導入も検討するとよさそう.

# Tailwindcss

CSSフレームワークは Bootstrap (opens new window) の一強だと思っていたがTailwind CSS (opens new window) というのがいつの間にか登場していたので導入する.

CSSのプロパティ値とHTMLのクラス名が定義されていて,そのクラスに変更するだけで所望のCSSを反映させることができる. 例えば .w-full をつけると width: 100%; が反映され, .bg-red-600 だと background-color: #e53e3e; といった形.

<p class="w-1/2 bg-blue-800 text-white">Test1<p>
<p class="w-full bg-blue-600 text-white">Test2<p>
1
2

Test1

Test2

自然とクラス数がやばくなって把握できなくなるのでメンテナンス性や可読性は悪そうだけど,ワンポイントで利用する分にはいい感じで利用できるのではないかという感じ.

インストールはyarnで一発.

yarn add -D tailwindcss autoprefixer
1

docs/.vuepress/convig.jsで設定する.

module.exports = {
    postcss: {
        plugins: [
            require("autoprefixer"),
            require("tailwindcss")(path.resolve(__dirname, 'tailwind.config.js')),
        ]
    },
}
1
2
3
4
5
6
7
8

設定ファイルを作成する.今回は初期設定のまま.

yarn tailwindcss init
mv tailwind.config.js docs/.vuepress/
1
2

cssが読み込まれるようにする.以下はデフォルトテーマ抽出後を想定しているが,もししていなければ実行しておくこと.

$ cd docs/.vuepress/theme/styles
$ mv index.styl index_base.styl

$ vi index.styl

@tailwind base;
@tailwind components;

@require 'index_base';

.theme-default-content p
  margin-top: 1em;
  margin-bottom: 1em;

@tailwind utilities;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

VuePressのバージョンアップで元々のindex.sylが劇的に変わるとしんどいのでindex_base.stylにリネームしてインポートするようにした. またtailwindによるmarginリセットで記事の余白が消されていたので.theme-default-content pで修正している.

自分で何かを追加したい場合は @tailwind components;@tailwind utilities; の間に指定するらしい.

ここまで完了すれば準備はOK.実行して動作確認をするとよい.

Last Updated: 2022/3/7 15:18:37