🔥

Honoを使ってNext.jsにPOSTページを実装しよう!

こんにちは、エンジニアの籏野です。
近年、弊社の作るWebアプリケーションはNext.jsを用いて開発されることが多いです。
Next.jsは高パフォーマンスなWebページを作るための様々な機能を内包したReactフレームワークであり、メジャーバージョンアップの際には次々と新しい機能が追加されています。

さて今回はとある事情により、POSTメソッドで描画されるページを実装したい要望が出てきたため、Next.jsでPOSTページを実現できるのか検証してみました。

結論

HonoをRoute Handlersで利用することで、Next.jsでもPOSTページを実装することができました。
実際に実装したコードは以下のリポジトリにありますので、合わせてご覧ください。

https://github.com/taku-hatano/nextjs_post_page_example

本記事ではHono以外にもどのような方法を検討したか合わせて紹介します。

検証

今回は以下のようにユーザー名を入力するフォームを用意し、SubmitするとHelloを返してくれるページに飛ぶアプリをベースに検証を行いました。

入力ページ
入力ページ

確認ページ
確認ページ

失敗ケース①: 普通にApp Routerでページを作成してみた

まずは単純にNext.jsのApp Router内に用意したページにPOSTメソッドでアクセスしてみました。
この場合ページの描画は問題なく行えますが、Next.jsのApp Routerではリクエスト内容からリクエストボディを取得する方法が提供されていないようでした。
そのため、POSTメソッドで送信したデータに基づいた描画が行えず、この方法ではPOSTページを実装することができませんでした。

https://github.com/taku-hatano/nextjs_post_page_example/blob/main/src/app/app-router/confirm/page.tsx

この検証結果から、Next.jsではPOSTページの実装は不可能であると諦めかけていたのですが、Next.jsにはApp Router以外にもRoute Handlersというリクエストの受け口があることを思い出しました。
かなりトリッキーではありますが、Route HandlersでHTMLを返せばPOSTページを実装できるのではと考えました。

成功ケース① HTMLを返すRoute Handlerを作成

以下の通りHTMLテキストをレスポンスすることで、リクエストボディから取得した内容を含めたページを描画することができました。
https://github.com/taku-hatano/nextjs_post_page_example/blob/main/src/app/route-handler/html/confirm/route.tsx

ただこの場合、HTMLテキストを直接記述する必要があり、すぐに辛くなることが目に見えています。
HTMLについてはApp Routerでの実装と同様にReactなどを用いて記述したいところなので試してみました。

失敗ケース② Reactコンポーネントから生成したHTMLを返すRoute Handlerを作成

しかしこの方法はNext.jsの仕様から実現できませんでした。
ReactコンポーネントをHTML文字列に変換するにはreact-dom/serverrenderToStringを使うのがよさそうですが、Next.jsではreact-dom/serverのimportが禁じられているようで以下のようなエラーが発生しました。

Error:
  × You're importing a component that imports react-dom/server. To fix it, render or return the content directly as a Server Component instead for perf and security.
  │ Learn more: https://nextjs.org/docs/getting-started/react-essentials

素のHTMLは書きたくないなーと思っていたのですが、ふと「HonoはJSXが書けるじゃないか!」と思い至り、Honoを使ってみることにしました。

成功ケース② Honoを使ってHTMLを返すRoute Handlerを作成

HonoをRoute Handlersで利用する方法は以下のページを参考にして下さい。

https://hono.dev/docs/getting-started/vercel

またHonoでJSXを扱う方法についてもドキュメントを参考にしてください。

https://hono.dev/docs/guides/jsx

一つ注意しなければいけない点は、Honoが提供するJSXはあくまでReactとは別物であるという点です。
ReactとHonoのJSXには記法の違いが存在するため、React用にセットアップしたプロジェクトではHonoのJSXの記法に対してエラーが発生してしまいます。
そこでHono用に作成するコンポーネントが存在するファイルではファイルの先頭で/** @jsxImportSource hono/jsx */を記述し、Hono のJSX記法を使用するよう明記する必要があります。
ここだけ注意すれば、JSXでHTMLを記述しレスポンスを返すことができます。

https://github.com/taku-hatano/nextjs_post_page_example/blob/main/src/app/route-handler/hono/confirm/route.tsx

また、まだExperimentalではありますが、HonoではReactのようにSuspenseを利用することができます。
これに非同期処理でデータを取得する必要がある際などに、先にページを描画しておくことができるのでとても便利です。

まとめ

今回はNext.jsでPOSTページをHonoを使って実装する方法を紹介しました。
Honoは他にも様々な機能を提供しつつ、いろいろなプラットフォーム上で動かすことができるので弊社でも利用する機会が増えてきました。
Next.jsでPOSTページを実装する際には、Honoを使ってみるのも一つの手かもしれません。

この記事を書いた人

籏野 拓
2018年新卒入社

FORCIA Tech Blog

Discussion