nuxt.js(v2) meta情報を１つのjsonに集約、各ページに反映されるようにする


こちらの記事、[nuxt.js(v2)でSEOに必要なmeta(OGP)で入力漏れの事故をなくす](https://qiita.com/amishiro/items/77e3c2546fa63cc69a62) で紹介されていた、metaまわりの実装をスッキリさせる方法を元に
ｍeta情報を一箇所で管理する方法をまとめます。

予め、この記事のもと設定が終わっている条件とします。

### 実現したいこと
- meta情報の一覧性を高めるため、メタ情報を一箇所で管理できるようにしたい。
- 各ページでmeta情報を定義するのをやめて、すべてのページのメタ情報が含まれるjson形式の定義ファイルを１つ作成しそこにまとめて書いたものが反映されるようにしたい

### 手順

- メタ情報をまとめた定義ファイルをjsonで作成
- nuxt.config でそれを読み込みを定義し、どこからでも参照できるように
- jsonで定義されたｍeta情報は、ファイルパスに基づいて各ページに反映されるように

### 準備

#### １． 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
```

#### ２． プロジェクト内で使用できるように、nuxt.config.js に読み込み設定

```nuxt.config.js
import metaData from './assets/data/metadata.json'

export default {
  env: {
    metaData: metaData
  },

```

これで、

```
context.env.metaData
```
でアクセスできるようになった。


### metaに反映


[記事](https://qiita.com/amishiro/items/77e3c2546fa63cc69a62) の本題と紹介されている部分 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
    }
```