【Vue + vue-mq】レスポンシブ対応でのVue実装について

# 目次
・[レスポンシブ対応での課題](#レスポンシブ対応での課題)
・[レスポンシブ対応での課題解決方法](#レスポンシブ対応での課題解決方法)
・[vue-mqとは](#vue-mqとは)
・[vue-mqの実装方法](#vue-mqの実装方法)
・[vue-mqでのデメリット](#vue-mqでのデメリット)
・[vue-mqのseo要件が満たされない可能性とは](#vue-mqのseo要件が満たされない可能性とは)
・[vue-mq実装時の動き](#vue-mq実装時の動き)


## レスポンシブ対応での課題
一般的な実装方法としては、PCやスマホなど各デバイス毎に各HTMLファイルを複数用意し最適化する手法を取っています。
レスポンシブ対応では、1つのHTMLファイルを、CSS3（Media Queries）で制御し、異なる画面サイズに応じてページのレイアウト・デザインを調整します。
その際、ここで問題となるのが「1つのHTMLファイル」。
一般的な実装方法を先ほど記載しましたが、基本PC・SPでHTMLが分かれている。
つまり、PC用のデザイン、SPの用のデザインとなっているため、それに合わせてHTML構造も異なります。

レスポンシブ対応する際は、デザイナーがPC・SPでの表示を考慮してデザインしたものを対応する場合はそこまで困らないですが、
今まであったものをそのままレスポンシブで対応するとなると、
デザイン的に考慮されていなかった表示をレスポンシブで対応しなければいけません。

そのため、「1つのHTMLファイル」とCSS3（Media Queries）での制御では実装的に苦しい部分が出てきます。

今回は、まさにこの内容で、
「今まであったものをそのままレスポンシブで対応」という要件があり、
HTML構造がPC、SPを「1つのHTMLファイル」で対応するとCSS側がごちゃごちゃするので、
こういった部分にだけ、vue側もレスポンシブ対応させようと思いました。


## レスポンシブ対応での課題解決方法
上記、課題解決の方法として、
vue実装であれば、「vue-mq」plugin を使用することで、課題解決ができそうだったので、
「vue-mq」plugin を試してみることにしました。

<a id="anchor3"></a>
## vue-mqとは
vue-mqは、Vueを使用してレスポンシブのブレークポイントを定義できるライブラリです。
セマンティックおよび宣言的にモバイルファーストの構築が行えます。

簡単にお伝えするとCSSのMedia QueriesのHTML版と考えてもらえるとわかりやすいかと思います。


## vue-mqの実装方法
基本的にはドキュメントを参考に実施してもらえれば問題なくできるかと思います。

ドキュメント：https://www.npmjs.com/package/vue-mq

一応、こちらにも実施手順を記載します。

### 1.Installation

Using NPM

```
npm install vue-mq
```

Using Yarn

```
yarn add vue-mq
```

### 2.ファイル作成

```
touch src/plugins/vue-mq.js
```

### 3.vue-mq.jsにブレイクポイントを記載

```js

import Vue from 'vue'
import VueMq from 'vue-mq'

Vue.use(VueMq, {
  breakpoints: {
    sp: 959,
    pc: 960
  },
  defaultBreakpoint: 'sp'
})
```

### 4.nuxt.config.ts(nuxt.config.js)にのplugins内にvue-mqを登録

```js

plugins: ['~/plugins/vue-mq'],
```

or

```js

module.exports = {
  plugins: [
    '~/plugins/vue-mq',
    ...
  ],
}
```

### 5.vue側での実装

```vue

<template>
  <div>
    <div>{{ $mq }}です</div>
    <div v-if="$mq === 'sp'">
      SPのtemplateです。
    </div>
    <div v-if="$mq === 'pc'">
      PCのtemplateです。
    </div>
  </div>
</template>
```

これにより、レスポンシブの対応で実装したMedia Queries同様に
vue側も表示領域に合わせたDOMに切り替わるため、
vueファイルは1つのままで、表示を切り替えることが可能となります。


## vue-mqでのデメリット
基本的にレスポンシブ対応には重宝すると思われる「vue-mq」ですが、いくつかデメリットも考えられます。

1、レスポンシブ対応と言いつつ、PC・SPでvue実装を分けているため、負債が多少残る可能性がある。（テンプレートを分けているのと似ているため）
2、SEO要件が満たされない可能性がゼロではない。（ここは最後に少しお話しします。）

大きなデメリットは無いと思われるものの、
よく考えてみると見えていなかったデメリットも見えてくるので実施に使用するか否かの判断は
慎重に決める必要があるかなと思います。


## vue-mqのSEO要件が満たされない可能性とは
vue-mqは実際のHTMLにはソースとして入っていないため、googleBotが正確に認識できているかという点が挙げられます。
よくSPAはSEO上はよくないとか、そういう話が昔あったと思います。
vue-mqの特徴として「画面サイズに応じてクライアントサイドで再レンダリング」されます。
そのためSSRとはまた違った動きになります。

注目すべき点は1つで、
「クライアントサイドで再レンダリングされる」、これがSEO的に問題ないか？という点になります。

私もここは気になったので少し調べてみたところ、そちらの内容を検証されている方の記事がありました。
https://logmi.jp/tech/articles/321993

内容的には以下になります。
>・2019年5月にGooglebotが急にアップデートを発表
>・アップデートにより「Webブラウザでユーザーが表示するのとまったく同様に」Googlebotがクローリングしてくれるようになった
>・検証結果としてPC、SPでの表示内容をGooglebotが認識している

上記内容から、
クライアントレンダリングがSEO的に問題と思われる節がありましたが、
そのような内容が解決してきている状況と見えそうですね。

## vue-mq実装時の動き
vue-mqを実際に実装した際の動きをcodepenに入れてみました。
下記のようにサイズが変化することで表示される内容が切り替わります。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="miyawash" data-slug-hash="JjoXPya" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="vue-mq sample">
  <span>See the Pen <a href="https://codepen.io/miyawash/pen/JjoXPya">
  vue-mq sample</a> by miyawash (<a href="https://codepen.io/miyawash">@miyawash</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>