【Vue.js】静的ホスティングでOGPをURL毎に変えて多言語対応させる

# 目的
URLに応じて、OGPの内容を切り替えたい。けどSSR（サーバーサイドレンダリング）は使わず静的ホスティングでやりたい。
例）
* hoge.com → 英語のOGPを表示
* hoge.com/ja → 日本語のOGPを表示

OGPを切り替えたかったらSSRで行うのが一般的ですが、静的ホスティングでも実現はできなくない。そういう記事がなかったので記録します。シンプルにしたいとか、サーバーの都合とかで静的ホスティングにしたい場合に活用できます。

# TL;DR
* [MPA](https://qiita.com/kamicop/items/c5c0917ed226234ee288)でプロジェクトを作成する
* 各htmlファイルに別々にOGPを記入する
* （多言語対応なら）各エントリーポイントで読み込むテンプレートは同一にして、読み込む言語ファイルを動的に変更する

## 最終構成図
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1050360/9225e345-cf3e-5140-1203-f4d32973ff9c.png)


# 留意点
* 多くのページ（例えばブログの各記事）にOGPを別々に設定する、などには不向きです
* 多言語対応くらいの、運用中に基本増えることがないような量であれば現実的です

# 参考記事
[Vue CLI 3でSPAではなくMPA(複数エントリーポイント)のプロジェクトを作成する](https://qiita.com/kamicop/items/c5c0917ed226234ee288)

# やり方

通常htmlファイルが一つなのがSPAで、Vue.jsの特徴でもありますが、複数のhtmlファイルを用いたMPAも可能です。
OGPを切り替えたいぶんだけhtmlファイルを用意し、それぞれに別々のOGPを記入したMPAプロジェクトを作成することで実現できます。

参考記事にMPAのセットアップ方法があり、そこで作成したhtmlファイルに別々のOGPを記入することで、「URL毎にOGPを切り替える」は実現できるので、ここでは割愛させていただきます。

そこから、多言語対応のために、

* テンプレートファイルを一つにする
* URLに応じて言語を切り替える

の2点をするのに必要なセットアップを説明します。

## vue-router
複数のURLに対してテンプレートファイルを一つにする場合、vue-routerはhashモードでないといけないです。historyモードだとルーティングがおかしくなってしまいます、、

## ファイル構成

私は日本語と英語に対応させたかったので2つ作成しました。中身は後述します。

* 英語用エントリーポイント
    * public/index.html
    * src/pages/en/main.js
* 日本語用エントリーポイント
    * public/ja.html
    * src/pages/ja/main.js
* テンプレートファイル（英語日本語共通）
    * App.vue

（図ではTypeScriptになっていますがJavaScriptでも同じです）

![スクリーンショット 2021-01-24 13.40.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1050360/5bc442ca-16ce-ed7e-6260-252c0a17f21d.png)

## main.jsの記述
次のように、main.jsを記述します。ポイントは、
* どちらも同じテンプレートApp.vueを読み込む
* `Vue.prototype.lang = 'en'` などと言語を指定する

```en/main.js
import Vue from 'vue';
import App from '@/App.vue';

Vue.config.productionTip = false;

// set language to english
Vue.prototype.lang = 'en';

new Vue({
  render: h => h(App)
}).$mount('#app');
```

```ja/main.js
import Vue from 'vue';
import App from '@/App.vue';

Vue.config.productionTip = false;

// set language to japanese
Vue.prototype.lang = 'ja';

new Vue({
  render: h => h(App)
}).$mount('#app');
```

## App.vueの記述
プロジェクトをvue-cliで作成したデフォルトのままで大丈夫です。

## vue.config.js

次のようにしてエントリーポイント毎にファイルを設定します。

```vue.config.js

module.exports = {
  pages: {
    top: {
      entry: 'src/pages/en/main.js', // エントリーポイントとなるjs
      template: 'public/index.html', // テンプレートのHTML
      filename: 'index.html', // build時に出力されるファイル名
      title: 'たいとる'
    },
    ja: {
      entry: 'src/pages/ja/main.js',
      template: 'public/ja.html',
      filename: 'ja.html',
      title: 'たいとる'
    }
  }
};
```

## OGPの記入
index.htmlには英語のOGPを、ja.htmlには日本語のOGPを記入します。

```index.html
    <!-- OGP -->
    <meta property="og:url" content="https://hoge.com" />
    <meta property="og:type" content="website" />
    <meta property="og:title" content="title" />
    <meta property="og:description" content="description" />
    <meta property="og:site_name" content="title" />
    <meta property="og:image" content="https://hoge.com/hoge.png" />
```

## 動作確認

ここまででのセットアップで、2つのURL`hoge.com/` と `hoge.com/ja`どちらもApp.vueのページが表示されるようになったはずです。そうなっていれば、最終構成図の矢印で示された接続は完成しています。[twitterシェアデバッガー](https://cards-dev.twitter.com/validator)などにURLを入力したら、2つのURLで別々のOGPが表示されるはずです。

## 言語の動的な切り替え
main.js で `Vue.prototype.lang='en'` などと設定したことで、テンプレート内のどこでも、`Vue.prototype.lang`とすることで今どの言語のページが表示されているかが読み込めるようになります。言語別に表現をjsonファイルなどで用意しておき、`Vue.prototype.lang` によって読み込みを変えることで多言語対応が実現できます。

App.vue内でURLを読み取って言語判定することもできますが、main.js内で行うとマウントの前に言語判定できて、またコードもきれいになると思います。

（例）

```langs.json
{
  "title": {
    "en": "TITLE",
    "ja": "たいとる
  }
}
```
```App.vue
<h1>{{ title }}</h1>
<script>
  created() {
    // langsJsonにlangs.jsonを読み込んでおく
    this.title = langJson.title[Vue.prototype.lang]
  }
</script>
```

# 具体例
こちらの仕組みで多言語対応を行ったサイトがこちらになります。
[ユーザーネームチェッカー](https://usrcheck.com)

# 課題
* hashモードを利用しないといけないためURLがきれいじゃない、、