Next.js13からCloudTasksにタスクを登録する際に、ハマったので記事にします。
事前準備
- CloduTasksでキューを作成
 - サービスアカウントにタスク追加のためのロールを追加
 - サービスアカウントのメール、シークレットキーを環境変数に登録
 - プロジェクトID、CloduTasksのロケーション、キューを環境変数に登録
 
目次
@google-cloud/tasksを使わない
僕がはじめにインストールした@google-cloud/tasksのバージョンは現在最新の5.4.0でした。
@google-cloud/tasks@5.4.0はローカルでは問題なく動きますが、CloudRunにデプロイする際にCloudBuildで以下のエラーがでました。
cannot find module '/app/node_modules/@google-cloud/tasks/build/esm/src/v2/cloud_tasks_client_config.jsonこのエラーの解決方法として、以下の2つが挙げられていましたが、どちらもうまく動きませんでした。
@google-cloud/tasksをダウングレードする
ダウングレードすることで解決する人はいるみたいです。
npm i @google-cloud/tasks@5.1.0
npm i @google-cloud/tasks@4.1.0しかし、@google-cloud/tasksは常に問題があるため使用しないことを勧めていました。
					GitHub
					
 					
			
						Error: Cannot find module Next.js 14 when module exists · vercel next.js · Discussion #64765
						Summary I get this error in dev mode and when building my Next.js app locally or on Vercel, but also in dev mode. Error: Cannot find module ‘C:\Projects\project…					
				outputFileTracingIncludesでjsonを読み込む
ビルド時に読み込めなかったファイルをnext.config.jsのoutputFileTracingIncludesで読み込んでおくことで、解決する人がいるようです。
しかし、僕は解決できず。。
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: "standalone",
  reactStrictMode: true,
  experimental: {
    outputFileTracingIncludes: {
      '/': ['./node_modules/@google-cloud/tasks/build/esm/src/**/*.json'],
    },
  }
};
export default nextConfig;
					GitHub
					
 					
			
						`@google-cloud/tasks` 4.1.0 causes cloud_tasks_client_config.json `no such file or directory` (publi…
						The following error happens with @google-cloud/tasks after updating from 4.0.1 to 4.1.0: Error: ENOENT: no such file or directory, open ‘/vercel/path0/fuu/node_…					
				google-auth-libraryを使ってCloudTasksにタスクを登録する
google-auth-libraryを使用するとビルドができたので、GoogleAuthで認証してからCloduTasksのキューにタスクを登録するようにしました。
import { GoogleAuth } from "google-auth-library";
import type { NextApiRequest, NextApiResponse } from "next";
export default async function createTasks(
  req: NextApiRequest,
  res: NextApiResponse
) {
  ...
  const projectId = process.env.GOOGLE_PROJECT_ID;
  const taskLocation = process.env.GOOGLE_TASKS_LOCATION;
  const taskQueue = process.env.GOOGLE_TASKS_QUEUE;
  if (!projectId || !taskLocation || !taskQueue) {
    return res.status(500).end("Missing environment variables");
  }
  const client = new GoogleAuth({
    credentials: {
      client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
      private_key: (process.env.GOOGLE_PRIVATE_KEY as string).replace(
        /\\n/g,
        "\n"
      ),
    },
    scopes: "https://www.googleapis.com/auth/cloud-platform",
  });
  const url = `https://cloudtasks.googleapis.com/v2/projects/${projectId}/locations/${taskLocation}/queues/${taskQueue}/tasks`;
  const today = new Date();
  const token = await client.getAccessToken();
  
  // タスクを作成
  const task = {
    httpRequest: {
      headers: {
        "Content-Type": "application/json",
      },
      httpMethod: "POST",
      url: "https://example.com/api/tasks/post",
      body: Buffer.from(
        JSON.stringify({
          message:'test',
        })
      ).toString("base64"),
    },
    scheduleTime: {
      seconds: Math.floor(new Date().getTime() / 1000),
    },
  };
  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ task }),
  });
    if (!response.ok) {
      console.log(`Error creating task: ${response.statusText}`);
    }
  }
  
  return res.status(200).end();
}

	







コメント