🐺

Next.jsのServer ActionsからSTORES APIにアクセスしてみる

2023/12/02に公開

外部のAPIにアクセスする際、api keyやcredential, tokenなどの機密情報をリクエストに含める必要があるケースが多いかと思います。

それらの機密情報を隠蔽するためにはサーバー側の環境変数を利用する方法が一般的でしょう。

Next.jsではサーバー側で動作させる仕組みとして以下の3つがあります。

Server ActionsはNext.js 13.4から追加された新しい機能で、App Routerでのみ使用できます。Page Routerを使っている場合は使用できない点に注意です。

今回はこれを使って外部のAPI(STORES API)にアクセスしてみました。

最終的なコードはGitHubにて公開しています。

https://github.com/t-aono/stores-pilot

リクエスト部分の実装

今回はSTORES APIの以下2つのエンドポイントに対してリクエストしています。

  • GET オーダー一覧
  • POST 在庫調整(ネットショップのみ)

サーバーコンポーネント

サーバーコンポーネントを作成して関数を定義します。

appフォルダー配下にstores.tsというファイルを作成しています。

Server Actionsを使うにはファイルの1行目に “use server” を書いて非同期関数を定義します。

"use server";

// オーダー一覧を取得するための関数
export async function getOrders() {
  const response = await fetch("https://api.stores.dev/retail/202211/orders", {
    headers: { Authorization: `Bearer ${process.env.STORES_API_KEY}` },
  });
  return await response.json();
}

// 在庫調整をするための関数
export async function updateInventory({
  variationId,
  quantity,
}: {
  variationId: string;
  quantity: number;
}) {
  const response = await fetch(`https://api.stores.dev/retail/202211/variations/${variationId}/inventories/adjustment`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.STORES_API_KEY}`,
        "Content-Type": "application/json",
      },
      cache: "no-store",
      body: JSON.stringify({ update_type: "absolute", quantity }),
    }
  );
  return await response.json();
}

STORES APIにアクセスするには、Authorizationヘッダーにcredentialを指定する必要があるのでfetchをする際に、headersでAuthorizationを書いています。

credentialの取得方法についてはSTORESのドキュメントを参照してください。

ローカルで動作させる場合、env.local を作成して環境変数を書いておく必要があります。

STORES_API_KEY=xxxxxxxxxx

クライアントコンポーネント

次にクライアント側で定義したServer Actionsの getOrders を呼び出してみます。

"use client";

import BaseButton from "@/components/BaseButton";
import { getOrders } from "../stores";

export default function Order() {
  async function fetchOrder() {
    const { orders } = await getOrders();
    console.log(orders);
  }

  return (
    <main className="container min-h-screen mx-auto p-8">
      <h3 className="font-medium">Order List</h3>
      <div className="mt-4">
        <BaseButton onClick={fetchOrder} label="fetch order" />
      </div>
    </main>
  );
}

App Routerdでは1行目に “use client” を書くことクライアントコンポーネントでであることを宣言します。tailwindcssを使って見た目の整えており、classNameについては本題から外れるので割愛します。

getOrders をインポートして呼び出すだけで、ボタンを押した際にリクエストが送信されレスポンスが返ってくるようになります!

サーバー側とクライアント側の繋ぎこみの部分がこれだけで実現できてしまうので、本当に便利だと感じます!

今度は updateInventory を呼び出してみます。

"use client";

import { updateInventory } from "./stores";

export default function Inventory() {
  async function postInventory() {
    const updateItems = {variationId: "", quantity: 10};
    const response = await updateInventory(updateItem);
    console.log(response);
  }

  return (
    <main className="container min-h-screen mx-auto p-8">
      <div className="mt-4">
        <BaseButton
          onClick={postInventory}
          label="更新"
        />
      </div>
    </main>
  );
}

POSTの場合も同様にインポートして実行できます!簡単ですね!

まとめ

Next.jsの新しい機能であるServer Actionsを使って外部のAPIにアクセスする方法についてコードベースで使い方を書いてみました。Next.jsで開発をする際の参考になれば幸いです。

サーバーコンポーネントでサーバーサイドの処理を手軽に書けるのは便利そうですね。Next.jsでは他にも便利な機能がたくさんありそうなのでぼちぼちキャッチアップしていこうと思います。

Discussion