クライアントサイドでのハイドレーション

entry-client.js において、以下の記述で私たちは簡単にアプリケーションをマウントします:

// これは、ルート要素に id="app" をもつ App.vue テンプレートを想定します
app.$mount('#app')

サーバがマークアップを描画後に、この処理を実行し、すべての DOM を再生成することを私たちは当然したくありません。代わりに、"ハイドレート (hydrate)"することで、静的なマークアップを単にインタラクティブにしたいです。

サーバの描画出力を調べたら、アプリケーションのルート要素が以下のような特別な属性を持っていることに気づくでしょう:

<div id="app" data-server-rendered="true">

この data-server-rendered という特別な属性は、クライアントサイドの Vue に、これがサーバ上で描画されたことと、この要素はハイドレーションモードでマウントしなくてはいけないことを知らせます。この属性はid="app"をタグに追加しないことに注意してください。それは単なるdata-server-rendered属性です。つまり、ID または 他のセレクタをあなた自身でルート要素に追加する必要があります。そうしないと、アプリケーションが適切にハイドレートできなくなります。

data-server-rendered属性を要素に指定しない場合でも、$mounthydrating実引数にtrueを指定することでハイドレートさせることができます。

// Force hydration of the app
app.$mount('#app', true)

開発モードでは、Vue はクラインアントサイドで生成された仮想 DOM が、サーバで描画された DOM の構成と一致しているかアサートを行います。もしこれが一致しない場合、 Vue はハイドレーションを取りやめ、サーバーが生成した既存の DOM を破棄して一から DOM の描画を行います。プロダクションモードでは、パフォーマンスの最大化のため、このアサーションは無効に設定されています。

ハイドレーション時の注意

サーバサイドの描画とクライアントサイドでのハイドレーションを行う時に一つ気をつけなければいけないことは、ある特定の HTML の構造はブラウザによって変換されてしまうかもしれないということです。例えば、あなたが Vue のテンプレート内に、以下のような記述をした場合です:

<table>
  <tr><td>hi</td></tr>
</table>

ブラウザは、自動で <tbody><table> に挿入します。しかし、Vue によって生成された仮想 DOM は、<tbody> を含みません。そのため、不一致が起こります。確実に一致させるためには、あなたのテンプレート内で必ず有効な HTML を記述してください。