こちらの記事、nuxt.js(v2)でSEOに必要なmeta(OGP)で入力漏れの事故をなくす で紹介されていた、metaまわりの実装をスッキリさせる方法を元に
meta情報を一箇所で管理する方法をまとめます。
予め、この記事のもと設定が終わっている条件とします。
実現したいこと
- meta情報の一覧性を高めるため、メタ情報を一箇所で管理できるようにしたい。
- 各ページでmeta情報を定義するのをやめて、すべてのページのメタ情報が含まれるjson形式の定義ファイルを1つ作成しそこにまとめて書いたものが反映されるようにしたい
手順
- メタ情報をまとめた定義ファイルをjsonで作成
- nuxt.config でそれを読み込みを定義し、どこからでも参照できるように
- jsonで定義されたmeta情報は、ファイルパスに基づいて各ページに反映されるように
準備
1. meta情報定義ファイル metadata.jsonを作成
ファイルパスに基づいてmetaデータを切り分けられるような構造にした。
独自のフォーマット。
例は、about、activity、works、projectsページがある場合の定義例。
metadata.json
{
"/about": {
"title": "about title",
"description": "about no description"
},
"/activity": {
"title": "activity title",
"description": "activity no description"
},
"/works": {
"title": "works title",
"description": "works no description"
},
"/projects": {
"title": "projects title",
"description": "projects no description"
},
}
ファイルはasset内に配置した。
@/assets/data/metadata.json
2. プロジェクト内で使用できるように、nuxt.config.js に読み込み設定
nuxt.config.js
import metaData from './assets/data/metadata.json'
export default {
env: {
metaData: metaData
},
これで、
context.env.metaData
でアクセスできるようになった。
metaに反映
記事 の本題と紹介されている部分 assets/mixins/meta.js の箇所に手を加えていきます。
mixin内で、metaData 値でアクセスできるようにする
metaData 値でアクセスできるように、asyncDataの箇所を追加します。
assets/mixins/meta.js
export default {
asyncData (context) {
return {
baseName: context.env.baseName,
baseDesc: context.env.baseDesc,
baseUrl: context.env.baseUrl,
baseOgp: context.env.baseOgp,
metaData: context.env.metaData, //←追加
}
},
.
.
.
head 関数内の調整
次に、head 関数内を調整していきます。
書くページのファイルのパスは、
.js
const path = `${this.$router.history.base}${this.$route.path}`;
で取れるようなので
やや雑な感じですがこのような感じにします。
assets/mixins/meta.js
head() {
const head = { meta: [] }
if (this.$route.path === '/') {
head.meta.push({ hid: 'og:type', property: 'og:type', content: 'website' })
}
// ページPath
const path = `${this.$router.history.base}${this.$route.path}`
if (this.metaData[path]) {
// タイトル
if (this.metaData[path].title) {
const title = `${this.metaData[path].title} - ${this.baseName}`
head.title = title
head.meta.push({ hid: 'og:title', property: 'og:title', content: title })
}
// ディスクリプション
if (this.metaData[path].description) {
const description = `${this.metaData[path].description}`
head.meta.push({ hid: 'description', name: 'description', content: description })
head.meta.push({ hid: 'og:description', property: 'og:description', content: description })
} else if (!this.metaData[path].description && this.metaData[path].title) {
const description = `${this.baseName}サイトの${this.metaData[path].title}ページです。${this.baseDesc}`
head.meta.push({ hid: 'description', name: 'description', content: description })
head.meta.push({ hid: 'og:description', property: 'og:description', content: description })
}
// ページタイプ
if (this.metaData[path].type) {
head.meta.push({ hid: 'og:type', property: 'og:type', content: this.metaData[path].type })
}
// OGP画像URL
if (this.metaData[path].image) {
const imageUrl = `${this.baseUrl}${this.$router.history.base}${this.baseOgp}${this.metaData[path].image}`
head.meta.push({ hid: 'og:image', property: 'og:image', content: imageUrl })
}
}
// ページURL
const url = `${this.baseUrl}${this.$router.history.base}${this.$route.path}`
head.meta.push({ hid: 'og:url', property: 'og:url', content: url })
return head
}