form
Netlify
generate
JAMstack
nuxt

楽勝すぎるはずの netlify form を nuxt generate で頑張って使う


netlify form が楽勝すぎる

netlify は静的ファイルのホスティングサービスだが、フォームを簡単に埋め込むことができる。

受託制作において、これまで簡単なフォームを埋め込むために PHP が動く環境で動かしていたので、

netlify を使えば、簡単に組み込む事ができて便利。

https://www.netlify.com/docs/form-handling/

詳細はドキュメントを見ていただければと思うが、 <form> タグに netlify の属性を追加するだけで、あとは通常どおり netlify 上で build して deploy すれば、なんとフォームが使えるようになる。


vue

<form name="contact" method="POST" netlify>

<p>
<label>Your Name: <input type="text" name="name" placeholder="新垣結衣"></label>
</p>
<p>
<label>Your Email: <input type="email" name="email" placeholder="yui@aragaki.love"></label>
</p>
<p>
<label>Message: <textarea name="message" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea></label>
</p>
<p>
<button type="submit">Send</button>
</p>
</form>

しかも、csv でダウンロードできるし、Slack に飛ばすことができるし、楽勝で form が使えます。

やっぱり netlify 好きです。


nuxt generate だと、全然楽勝じゃない、、

ただ、上記 html を vue コンポネントの template 書いて、nuxt generate したファイルを netlify に上げてもうまくいかなかった。

具体的には、下記のエラーが developer tools の console に出た。

[nuxt] Error while initializing app DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.

at Object.appendChild

これは、生成された html と component を利用してレンダリングをする html が異なる場合に、エラーになるっぽい。(多分)

また、<nuxt-link> での dom書き換えによる遷移後も、エラーがでないものの通常のPOSTのフォームの挙動となり、正常に動作しなかった。


原因

そこで、netlify にホスティングされた生成された html をみると、


vue

<form name="contact" method="POST">

<input type="hidden" name="form-name" value="contact">
<p>
<label>Your Name: <input type="text" name="name" placeholder="新垣結衣"></label>
</p>
<p>
<label>Your Email: <input type="email" name="email" placeholder="yui@aragaki.love"></label>
</p>
<p>
<label>Message: <textarea name="message" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea></label>
</p>
<p>
<button type="submit">Send</button>
</p>
</form>

<input type="hidden" name="form-name" value="contact"> が追加されていることがわかった。

build するときに、html をパースして、type="hidden"の input を差し込んでくれているみたい。

そしてそのとき合わせて POST のAPIを作ってくれることで、静的ホスティングサービスなのに、フォームが実現できるようだった。

だが、nuxt で作られるコンポーネントの dom は、この置換がされていないので、通常のフォームの挙動になってしまうし、nuxt が予期せぬ html があるということでエラーが出てしまっているのが原因っぽい。


解決策

まず console のエラーをなくす解決策として、<no-ssr> タグを使うことで、generate する HTMLを無くして、ズレをなくした。


vue

<no-ssr>

<form name="contact" method="POST">
<input type="hidden" name="form-name" value="contact">
<p>
<label>Your Name: <input type="text" name="name" placeholder="新垣結衣"></label>
</p>
<p>
<label>Your Email: <input type="email" name="email" placeholder="yui@aragaki.love"></label>
</p>
<p>
<label>Message: <textarea name="message" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea></label>
</p>
<p>
<button type="submit">Send</button>
</p>
</form>
</no-srr>

すると無事エラーはとれた。※ type="hidden"の input は含めたままにする。

が!これではパースされる html がないので、今度はフォームのPOST APIが作られずに、通常の

タグが埋め込まれるだけになってしまう。

次に、static/form.html を用紙し、form.html


form.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>おといあわせ</title>
<link rel="stylesheet" href="">
</head>
<body>
<form name="contactform" method="post" netlify >
<input name="name" type="text" class="input is-success" placeholder="新垣結衣">
<input type="email" name="email" class="input is-success" placeholder="yui@aragaki.love">
<textarea name="message" class="textarea" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea>
</form>
</body>
</html>

とnuxt generate とか関係ないダミーの html を用意し、build 時に POST API を作らせるようにした。

ちなみに、このパースされたフォーム内にある input の name 属性しか、paramで投げても受け入れてくれないので、 .vue と input の数や属性は、揃える必要があった。

また一応このあたりで、リダレクトをかけることでダミーにはアクセスできないようにもできる。

https://www.netlify.com/docs/redirects/

こうすることで、なんとか nuxt generate で生成したファイルでも 頑張って netlify form 使うことに成功した。

が、頑張って使ってて、全然スマートじゃないので、なんかいい方法あれば教えてください。