はじめに
Diverseのアドベントカレンダー、5日目担当のshiranuikです。
私は現在Youbrideというサービスの、WebフロントエンドのNuxt化を進めています。
現状のYoubrideでは、古き良きPerlによってHTMLを書き出しています。
いきなり全ては捨てられない……でも今後を考えるとフロントエンドとバックエンドは切り離せるようにしたい……。
そこで「nuxt generate だ!」
※このあたりの具体的なお話は、日と場所を改めてそのうち公開されることと思います。
今日はNuxt化に日々取り組んでいて、最近一番困った件を紹介します。
nuxt generate 後に謎のエラー
nuxt dev
実行ではエラーが出ないのに、generate後のページにアクセスするとJavaScriptのエラーが出てる!
……というのがそもそもの発端です。出ていたエラーはこんな感じ。
Failed to execute 'appendChild' on 'Node': This node type does not support this method.
なんだろう?
子要素を追加できない、つまりNuxtがViewを生成するときに失敗しているっぽい。
ダミーデータを使っているローカル開発環境では発生しないので、多分PerlからNuxtに注入しているデータが悪い……のかもしれない?
試しに渡すデータを空っぽや静的なものにしてみる。
⇒ エラー変わらず。注入しているデータの問題ではない。
ではどこかHTMLの構造に問題があるかもしれないから、一度まっさらな状態にしてみよう。
⇒ エラーが消えた!
少しずつ戻してどこの箇所が問題か探る。
⇒ Formタグ……?
ここでようやく、実際に表示されているHTMLとdistにある生成されたHTMLを比べてみました。
すると、何か知らない<input type='hidden' name='hoge' value='fuga'>
が追加されている!! これか!!!
どうしてこうなった
該当のタグはPerl側でFormタグがあるときに問答無用で追加していました。
Nuxt側が覚えているHTML要素と生成されたHTML要素が違うと該当のエラーが発生するようです。
(※完全に描画する前にJavaScriptの処理が止まってしまうため、データが取得できなかったり、計算が止まってしまったりの状態になります。そのため、上記エラー以外にも、slot周り等のエラーが出たりもしていました)
該当のタグは埋め込まないといけない。要素の数を揃えないといけない。どうしよう。
ではこうしよう。
<templete>
<form method="post">
<input type="hidden" name="hoge" id="hoge"/>
<input type="mail" name="mail"/>
<input type="password" name="password"/>
<input type="submit" value="login"/>
</form>
</template>
<script>
export default {
name:'login',
data(){
return {
hoge:null,
}
},
/** mountedに入る前に、hogeにはサーバから渡されたデータが入っている **/
mounted(){
if (!this.hoge) {
document.getElementsById('hoge').forEach((value) => {
value.value = this.hoge;
});
}
}
Nuxtの該当箇所に空っぽの<input type='hidden' name='hoge'>
を用意します。
これで一旦エラーは出なくなりますが、DOM生成後には本来埋め込んでいた値が消えてしまっています。
DOMの準備が終わったmounted
の中で、別の手段で受け取っていた値を流し込んでいます。
まとめ。
nuxt generate後のHTMLに何か追加するときは、エラーになることがあるので気をつける。
空の要素を用意しておき、後から値を代入すると問題なく動く。
generate後のHTMLに後から何か挿入したり書き換えたりは通常あまり無いと思うのですが、原因不明のJavaScriptエラーが出たときにでも思い出してみてください!