NuxtJSのSSRモードでAdsenseが発行するタグを貼ると以下のエラーが発生した。
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content.
This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>,
or missing <tbody>. Bailing hydration and performing full client-side render.
簡単にいうとサーバーでレンダリングされたDOMとクライアントサイドでレンダリングされたDOMに差異があるという警告で開発モード(yarn dev
等)で起動したときのみ発生する。本番サーバーを起動(yarn start
等)したときは以下のエラーが発生し、DOMが表示されなくなる(つまりなにもできないバグが発生)
DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
at Object.appendChild (https://my.domain/_nuxt/vendors/commons.3cf3456.js:5196:8)
ハイドレーションがなんぞやという人はこちら↓
https://ssr.vuejs.org/guide/hydration.html#client-side-hydration
時間ない人用和訳
ハイドレーションとは、Vueがサーバーから送信された静的HTMLを引き継ぎ、クライアント側のデータ変更に対応できる動的DOMに変換するクライアント側のプロセスを指します。
どのDOMが悪さしているか調べる
devツールのConsoleタブで該当のエラーを調べ、hydrateのリンクをクリックする。
ブレークポイントを貼り、リロードすると止まるのでvnodeあたりを見るとエラーが発生した箇所がわかりやすい
対処法
- client-onlyを使う
クライアントのみでレンダリングするためのコンポーネント。
<client-only></client-only>
- no-ssrを使う
サーバーサイドレンダリングの対象からコンポーネントを除外するためのコンポーネント。
<no-ssr></no-ssr>
- 無効なHTMLを直す
table
タグ内にtbody
がないようなことはよく発生するらしいので、変なHTMLがあれば直す
おわりに
Adsenseで発生したが、毎回発生するわけじゃないので結構厄介だった。さらにこの方法でもAdsenseが悪さしてるって特定できなかったので、同じように困ってる人がいれば検索で引っ掛かれば良いなと思っている。もしかしたらNuxtのAdsenseライブラリを使えば起きないかもしれない。。(個人的には使いたくない。。)vuetifyのDatePickerでも同様の事象が起きるらしいので同様の対処すればよいのかと