GAミント至上主義

Web Monomaniacal Developer.

NuxtJSでhead内のbaseタグをhooksを使って無理やり消してAMPエラー解消した

ちょっと無理やりなややこしいことをしたのでその経緯を含めてメモ。設定でできるようになるといいな。

NuxtJSでAMP対応をしてますが、router.baseを設定しサブディレクトリに公開しているため、headにbaseタグが入ってしまい、これがAMPテストツールのエラーの原因になっていました。

テストツールはこれ→https://search.google.com/test/amp?hl=ja


f:id:uyamazak:20200702184539p:plain

一通りググったけどそれらしい方法は見つからず。
サブディレクトリかつ、AMP対応というレアケースのためでしょうか。

API: router プロパティ - NuxtJS

ドキュメントには

base がセットされているときは Nuxt.js はドキュメントのヘッダーに を追加します。

と書いてあるだけで消し方などは書いてありません。

pageファイル内のhead()で試しましたがダメ。

ということでソースコードにあたりました。デフォルトブランチへのリンクなので変わってしまうかも。

今日(2020/7/2)時点のdevブランチだと、SSRの場合ここでbaseタグを挿入してます。
github.com

文字列連結してるのでhead()でいじれないのは当たり前でした。

    // Add <base href=""> meta if router base specified
    if (this.options._routerBaseSpecified) {
      HEAD += `<base href="${this.options.router.base}">`
    }

this.options._routerBaseSpecifiedを変える手もあるかと思いましたが今後、他でも使われるかもしれないし、_がついてるので触っちゃだめなはず。nuxt.config.jsからも渡せません。

何か方法はないものかと、ソースコードをたどるとhookというものを見つけました。

https://github.com/nuxt/nuxt.js/blob/dev/packages/vue-renderer/src/renderers/ssr.js#L268

await this.serverContext.nuxt.callHook('vue-renderer:ssr:templateParams', templateParams, renderContext)

hookの使い方の例はここにありました。
API: hooks プロパティ - NuxtJS

import fs from 'fs'
import path from 'path'

export default {
  hooks: {
    build: {
      done (builder) {
        const extraFilePath = path.join(builder.nuxt.options.buildDir, 'extra-file')
        fs.writeFileSync(extraFilePath, 'Something extra')
      }
    }
  }
}

ということでやってみた。vue-renderer:ssr:templateParamsをコロンで切ってオブジェクト化して、最後を関数にすればいいらしい。


nuxt.config.js

export default {
  hooks: {
    'vue-renderer': {
      ssr: {
        templateParams(templateParams, renderContext) {
          // AMPページでbaseタグを無理やり消してる
         if (renderContext.url && renderContext.url.match(/\/amp\/?$/)) {
            templateParams.HEAD = templateParams.HEAD.replace(
              `<base href="${BASE_PATH}/">`,
              ''
            )
            console.log('base tag removed', renderContext.url)
          }
        },
      },
    },
  },

今回baseタグを消すのは、AMPページだけでいいので判定にはrenderContext.urlの最後に/amp/が付いているかどうかを使いました。
というかこれぐらいしか見つからなかった。

これで無事?AMPページだけ消えました。
設定でやりたいから要望、プルリクを思ったけどレアケースかもしれないので悩んでる。

Nuxt.jsビギナーズガイド

Nuxt.jsビギナーズガイド

Vue.js&Nuxt.js超入門

Vue.js&Nuxt.js超入門