Next.jsのServer Actionが凄かったのでご紹介

2023/07/28に公開

Server Actionとは

Next.jsのバージョン13.4で新たに追加された機能で、
端的にいうと、クライアント側でデータ管理処理を持たず、サーバー上でデータ更新を行うことができる機能となります。
公式ではzero client JavaScriptと謳っており、提供する機能によっては実際にzeroにすることができるポテンシャルを秘めています。

何がすごいのか

  1. サーバ上でデータ更新 (作成、更新、削除) を行うことができるため、fetch関数などを利用したクライアント (ブラウザ)用のコードを記述することなくデータ更新ができます。

  2. データ更新に関係するコードがクライアント側で必要なくなるため、クライアントがダウンロードするJavaScriptコードの削減につながります。(見せたくないものを隠すと言った運用もできるようになるよ!)

  3. プログレッシブエンハンスメントなフォームを作成することができるため、JavaScriptが利用できない環境でもフォームを利用することができます。
    ブラウザの拡張で通報が多くJSを実行禁止に指定されているサイトでのデータ収集なども可能なことや、
    JavaScriptが無効化されている環境でも認証フローが正常に機能するように設計することが可能です。
    Bearer認証の場合、ユーザーがログインするとサーバーはBearerトークンを生成し、それをクライアントに返します。その後、クライアントはこのトークンを使用して認証が必要なリクエストを行います。このトークンの生成や検証のプロセスは、Server Actionsを使用してサーバーサイドで行うことができます。

公式から発表されている情報でパッと思いつくメリットとしては上記の内容がありますが、使い方に汎用性が高すぎるのでおそらく今後は公式も想定していない使い方をする人が出てくると思います。

サンプル実装

公式で取り扱っているサンプルに解説をつけてご紹介します
https://nextjs.org/blog/next-13-4#server-actions-alpha

一つ目のサンプルは

app/post/[id]/page.tsx
import kv from './kv';

export default function Page({ params }) {
  async function increment() {
    'use server';
    await kv.incr(`post:id:${params.id}`);
  }

  return (
    <form action={increment}>
      <button type="submit">Like</button>
    </form>
  );
}

このコードでは、increment関数がServer Actionとして定義されています。この関数は、'use server'ディレクティブを使用してサーバーサイドで実行されます。この関数は、キーpost:id:${params.id}の値をインクリメントする操作を行います。

そして、このincrement関数は、フォームのaction属性として指定されています。これにより、フォームが送信されると、increment関数が実行されます。

次のサンプルコードはフォームデータをDBに挿入し、その後でリダイレクトする処理となっています。

app/post/[id]/page.tsx
import db from './db';
import { redirect } from 'next/navigation';

async function create(formData: FormData) {
  'use server';
  const post = await db.post.insert({
    title: formData.get('title'),
    content: formData.get('content'),
  });
  redirect(`/blog/${post.slug}`);
}

export default function Page() {
  return (
    <form action={create}>
      <input type="text" name="title" />
      <textarea name="content" />
      <button type="submit">Submit</button>
    </form>
  );
}

Server Actionとして定義されているcreate関数でフォームデータを受け取り、そのデータを使用してDBへのポストを行います。

まとめ

クライアントに見せずにデータ登録などが可能な点は、クライアント側から見ると懸念されるケースにつながる可能性もあるかもしれません。その意味で自分としては尖った技術に感じました。

しかし、JSを使用せずサーバーサイドだけで認証などに使用できるといった、正当性のあるサイトや、ブラウザのバージョンによっては稼働しないと言った環境差分を吸収できるといったメリットもとても多く、今後に期待されます。

レスキューナウテックブログ

Discussion