GAミント至上主義

安くて速いが好きなWEBアプリ開発者。最近はPython, Vue.js, Firebase, GKE。@株式会社ビズオーシャン

vue-routerでtitleとdescriptionを動的に切り替える

yagishの公開から2週間ぐらいたち、Googleサーチコンソールをみるとtitleタグが同じ、descriptionが同じという、SEO対策でよくある初歩的な警告を目にしたので、なんとかする。

rirekisho.yagish.jp

SPAのSEOはまだ情報が少なくSSR(さーばー・さいど・れんだりんぐ)しないとダメみたいな記事もある。でもSSRをしてないyagishでそんな警告が出るってことはすでにボットがレンダリングしてちゃんと読んでいるもよう。

現在、WebpackでビルドしたフォルダをFirebase Hosting置くだけですみ、運用が楽すぎるので、可能な限り今後もSSRなしでいきたいと思う。

fetch as googleも問題なさそうだし、SEOのためだけのSSRはコスト的にどうなんだろうと思った。

で、titleとmeta descriptionの設定をしてみた。

最初のルーティング設定は下記のような感じで、URL内の変数formatIdを使って履歴書の種類を取得しているが、titleは固定なのでその書式名はtitleに入っていない。

router/index.js

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/format/:formatId',
      component: formatDetail,
      props: true,
      name: 'formatDetail',
      meta: {
        title: '詳細 - ' + SITE_TITLE
      }
//省略

router.afterEach((to, from) => {
  if (to.meta && to.meta.title) {
    document.title = to.meta.title
  }
})

そのため、formatIdを渡すとその書式のタイトルなどを返す関数を作る。
データがどこにあるかで実装は大きく異なると思うので、省略する。
ちなみに現在のyagishはローカルのjsファイルにオブジェクトとして書いてあるのでfilterで取ってきてる。

const getFormatMeta = function (formatId) {
  const result = () =>{  /* formatIdでデータを取得する処理 */ }
  return {
    title: result.title,
    description: result.description,
  }
}

次にtitleはdocument.titleで簡単に取得できるが、metaタグのdescriptionは一発では取れずちょっと面倒なので、html側でidを振って、安心と信頼と実績のgetElementByIdで取得することにする。

index.htmlのhead内

    <meta name="description" id="head-meta-description" content="yagish(ヤギッシュ)はブラウザ上で履歴書がつくれる無料サービスです。記入例や入力補助機能がついた履歴書テンプレートを選んで入力するだけ。自宅でも外出先でも、スマホでもパソコンでも、必要なときにいつでも履歴書を作成できます。">

要素とindex.htmlに記述済みのものを変更前にデフォルト値として取っておく。

router/index.js

const metaDescriptionElement = document.getElementById('head-meta-description')
const defaultDescription = metaDescriptionElement.content

// afterEachに追加
router.afterEach((to, from) => {
  if (to.meta && to.meta.title) {
    if (to.params.formatId) {
      const formatMeta = getFormatMeta(to.params.formatId)
      document.title = formatMeta.title + ' - ' + to.meta.title
      metaDescriptionElement.content = formatMeta.description
    } else {
      document.title = to.meta.title
      if (to.meta.description) {
        metaDescriptionElement.content = to.meta.description
      } else {
        metaDescriptionElement.content = defaultDescription
      }
    }
  }
})

とりあえず動いたけど、タイトルを整形する関数とかいろいろ整理しないとページが増えてきたらこのままではやばそう

速習Vue.js 速習シリーズ

速習Vue.js 速習シリーズ

Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))

Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))