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

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

受託制作において、これまで簡単なフォームを埋め込むために PHP が動く環境で動かしていたので、
netlify を使えば、簡単に組み込む事ができて便利。

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

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


```html: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 をみると、

```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>`~~ `<client-only>` タグを使うことで、generate する HTMLを無くして、ズレをなくした。

※追記 2020/02/05 `<no-ssr>`は、nuxt3 から deprecated みたいなので、`<client-only>`のが良さそうです。

```html:vue 
<client-only>
<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>
</client-only>
```

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

追記 2020/02/05現在 ダミーを作らなくても API を生成してくれるようになったみたいです。
@kkotaro0111 さん情報ありがとうございます。


~~が！これではパースされる html がないので、今度はフォームのPOST APIが作られずに、通常の<form> タグが埋め込まれるだけになってしまう。~~

~~次に、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 使うことに成功した。

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