🔖

フロントエンド初心者がVueで作ったブログをNuxtのSSGで作り直した時につまずいたこと

2021/09/07に公開

概要

業務で触れる技術はバックエンド関連が主で、フロントエンドを関連の技術に触れることが少ないのですが、勉強を兼ねてVue.jsとContentfulで作成したブログをSPAで、Netlifyにホスティングしていました。

その後、パフォーマンスの向上+OGPの設定を目的として、Nuxt.jsのSSG機能を使って書き換えてみました。

リンク

リプレイス後

https://github.com/shira79/MyBlog
https://shira-nuxt-static.netlify.app/

使用技術は以下です。
Nuxt.js or Next.js + Contenful + Netlify or Vercelの構成でブログを作成する記事はたくさんあるので、それらを参考にしてます。

リプレイス前

https://github.com/shira79/VueBlog
https://shlia.netlify.app/

リプレイス時のつまづき

リプレイスする際に、いくつかつまづきがありました。その内容と解決策を羅列します。

もっと別のいいやり方があれば、コメントしていただけると嬉しいです><

ページネーションについて

静的ページの場合、ページネーションをどのように実装するかという問題が発生します。

他の記事をみると以下のように実装しているものが多く、参考にさせていただきました。

SSGでページネーションを作成する場合は、SSRと違って/page/1、/page/2のようにして、各ページ毎にコンテンツを取得するのがベターです。

https://blog.microcms.io/next-pagination/

記事の件数が少ない場合、記事の一覧情報を全件HTMLにセットしておいて、クエリの指定で表示/非表示を制御する方法もあるようです。

ちなみにページネーションコンポーネントの実装は、
vuetifyのv-paginationコンポーネントを元に作成し、数字のボタンが押されて切り替わったら、${this.base_path}/${new_page}に遷移する、というようにしています。

<template>
    <v-container>
        <ul class="pagenation">
            <li>
                <nuxt-link :to="getTargetRoute(current_page-1)" :class="{'is-disabled':current_page-1<1 }" >
                    <button class="page-btn" ><</button>
                </nuxt-link>
            </li>
            <li v-for="page in last_page" :key="page">
                <nuxt-link :to="getTargetRoute(page)">
                    <button class="page-btn" :class="{'selected':page==current_page }">{{page}} </button>
                </nuxt-link>
            </li>
            <li>
                <nuxt-link :to="getTargetRoute(current_page+1)" :class="{'is-disabled':current_page+1>last_page }">
                    <button class="page-btn">></button>
                </nuxt-link>
            </li>
        </ul>
    </v-container>
</template>

<script>
    export default {
        props:{
            current_page: {
                type: Number,
                required: true
            },
            last_page: {
                type: Number,
                required: true
            },
            base_path: {
                type: String,
                required: true
            },
        },
        methods:{
            getTargetRoute(page){
                // pageが不正だったら空文字を返す。現在のパスを指定
                if(page<1 || page>this.last_page) return "";
                if(page == 1){
                    return `${this.base_path}`;
                } else {
                    return `${this.base_path}/${page}`;
                }
            },
        },
    }
</script>

https://github.com/shira79/nuxt-blog/blob/main/components/Pagination.vue

generateしたページをどうやって確認するか

npm run generateで生成したページをどうやって確認するのがいいんだろうと思ってました。

初期は/dist下のhtmlファイルをブラウザで表示してみるというIQ低めの方法でやってましたが、流石になんとかせねばと思って調べました。

現在はnuxt serveというコマンドを使っています。
https://blog.microcms.io/nuxt-full-static-generation/

上記を知らなかった時は少し前は、http-serverというパッケージ使って確認していました。
https://papadays.com/post/6gozzcufrbylieiwjyox9r/

markdown関連のライブラリ選定

過去Vueで作っていたときに、markdownのパースにはmarked.jsを使っていました。

実装の途中で見出しの機能を追加したいと考えるようになりました。その場合、markdown-itというライブラリであれば、楽に実装できることがわかったため、切り替えました。

こちらの記事を参考にしました。
https://blog.nakamu.life/posts/vue-markdown-nuxtjs-markdownit

markdown関連では、結果的に以下のライブラリにお世話になっております。

nuxt.config.js

markdownit: {
breaks: true,
use: [
    ['markdown-it-table-of-contents', {
        includeLevel: [2, 3],
    }],
    ['markdown-it-anchor'],
],
highlight: (str, lang) => {
    const hljs = require('highlight.js');
    return '<pre class="hljs"><code>' + hljs.highlight(lang, str).value + '</code></pre>';
  },
},

asyncDataはpageコンポーネントでしか使えない

Twitter、GithHubといったソーシャルリンクはContentfulからデータを取得しています。
複数箇所で使っているので、VueではSocials.vueというコンポーネントを作り、その内部からapiを叩いていました。

しかし、NuxtのSSGで使用するasyncDataはpageコンポーネントからしか使えません。

このフックはページレベルのコンポーネントのためだけに使うことができます。

https://ja.nuxtjs.org/docs/2.x/features/data-fetching/#async-data

各pageコンポーネントでデータ取得して、取得したデータをSocials.vueに渡すという実装に変えて対応しました。

TwitterでOGPが表示されない

静的ページに切り替えるにあたって、同時にOGPを設定したいと思いましたが、TwitterのOGPがうまくいかずハマりました。
twitter:cardはちゃんとhtmlのheadに記載しているのになぜ??と困っていましたが、デバックの手段はしっかり用意されていて、以下を使用すればすぐ原因が特定できます。
https://cards-dev.twitter.com/validator

やってみたところ、og:titleが不正だとと言われました。

titleがあれば十分なのかなと勝手に思い、追記しておりませんでしたが、og:titleも必須なようです。
https://qiita.com/Hosh0801ict/items/86bd0810fe57a4620f9e

404ページ

何も設定しないと、Nuxtで用意した404ページではなく、Netlify自体の404ページが表示されてしまいました。

nuxt.config.jsのgenerateプロパティでfallbackオプションを設定することで、不明なルートもNuxtを介すようになります。つまりエラーページを表示できます。

フォールバックとは、 情報通信の世界では「(障害などに起因する)代替手段への切り替え」を意味します。

fallbackのドキュメント

終わりに

もっと別のいいやり方があれば、コメントしていただけると嬉しいです><

Discussion