Cloudflare:(1)
2026年8月10日ローカルエクスプローラー:
➜ Local: http://localhost:3000/
➜ Network: use --host to expose
➜ Debug: http://localhost:3000/__debug
➜ press b + enter to list configured Cloudflare bindings
➜ press e + enter to open local explorer
➜ press t + enter to start tunnel
➜ press h + enter to show helptanstack-startの場合、ターミナルでe + Enter をするとPrsima Studioのようなダッシュボードが表示される。
この機能はCloudflare統合のプラグイン設定をすると他のフレームワークでも使用できる。
API:
workersにデプロイする場合は
env.でR2やKVといったバインディングと接続ができるが、VercelやNetlifyにデプロイする場合は出来ない。VercelやNetlifyでVercelのバインディングを使う場合HTTP接続で行う。APIトークンを作成し認証headerに含める。
環境変数とbinding
重要:
npx wrangler secret put SECRET_NAMEで環境変数の設定、npx wrangler d1 create NAMEなどで各種Cloudflareの機能( = binding)を作成しアプリに追加するが、それを行うたびにnpx wrangler typesコマンドを実行しworker-configuration.d.tsという型定義ファイルに型を生成する。
環境変数・bindingの削除:
環境変数:
npx wrangler secret delete SECRET_NAMEbinding:
wrangler.jsoncから該当するものを削除し、wrangler typesコマンドで型からも削除
Workers
Node.js前提のライブラリは機能しないことがあるので調べて対応
workers.devドメインはアカウント名がドメインに入る。
Nextjs:
Node.jsランタイムではないWorkersではそのままだと動かない。
OpenNext:https://opennext.js.org/
R2
npx wrangler r2 bucket create/delete NAME
====
"r2_buckets": [
{
"bucket_name": "",
"binding": "",
"remote": true,
},
],やること:ダッシュボード
パブリック開発URLの作成
CORS
{
"AllowedOrigins": [
"http://localhost:3000",
"本番ドメイン"
],
"AllowedMethods": [
"GET",
"POST",
"DELETE"
]
}URL:
開発時 - パブリック開発URL / 本番 - カスタムドメイン
バケット:
1のバケットを1つのR2用カスタムドメイン(
cdn.example.com)で使いまわすことは出来ない。「既に紐付いているバケットがある」旨のメッセージが出る。
// X
cdn.example.com → bucket1
cdn.example.com → bucket2
// O
cdn1.example.com → bucket1
cdn2.example.com → bucket2Vercelと画像サイズ:
1MB以上の画像をserverActionで処理しようとすると画像のUploadが出来ない。
Vercel-Log
Uncaught Exception: Error: Body exceeded 1 MB limit.
fileのsizeプロパティが1,000,000 bytes = 1MB以下かチェックを入れる。
upload例:
import { env } from "cloudflare:workers";
import { createServerFn } from "@tanstack/react-start";
export const uploadImageFn = createServerFn({ method: "POST" })
.validator((data) => {
if (!(data instanceof FormData)) {
throw new Error("Expected FormData");
}
return data;
})
.handler(async ({ data }) => {
const image = data.get("image") as File;
const arrayBuffer = await image.arrayBuffer();
await env.cflare_eco.put(image.name, arrayBuffer, {
httpMetadata: {
contentType: image.type,
},
});
});env.BUCKET.put/get/delete()await image.arrayBuffer()でFileオブジェクトからバイナリデータを取り出しUploadするのは、どのCloudでも共通した流れwebpはpngの1/10くらいのサイズなのでwebp変換を関数に取り入れるのもあり
<img src={`${env.VITE_R2_ENDPOINT}/icon128.png`} alt="" />TTL:
設定はダッシュボード側のライフサイクルルール設定から行う。
ルール範囲のプレフィックス:
generated/にしたらgenerated/フォルダ内が該当generatedだけならgenerated/フォルダ内やgenerated-icon.pngのようなアセットが該当
workers以外でデプロイ
VercelやNetlifyでデプロイする場合、workersAPIではなくS3互換APIを使用する。
const r2Client = new S3Client({
region: "auto",
endpoint: `https://${env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: env.R2_ACCESS_KEY_ID,
secretAccessKey: env.R2_SECRET_ACCESS_KEY,
},
});
}アクセスキー/シークレットキーはR2ダッシュボードからAPIトークンを「管理者読み取りと書き込み」をONにして作成することで取得できる。*作成後は値を確認できない。
KV
key/valueペアのストレージ、使い方はRedisと類似
npx wrangler kv namespace create/delete NAMESPACEenv.NAMESPACE.get/put/delete(key, value)既存のkeyにputをすると上書き
TTL(time to live):
await env.SUMMARY.put(id, result.response, {
expirationTtl: 60 * 60 * 24 * 5, // 5日間
});最小は60秒
オブジェクトや配列:
const user = {
id: 123,
name: "hoge",
email: "hogetge@gmail.com",
};
await env.kv_test.put(`${user.id}`, JSON.stringify(user));
const created = await env.kv_test.get("123", {
type: "json",
});取得時にtype:"json"を付けると
JSON.parse()が必要なくなる。保存時にはそのような機能はないので
JSON.stringify()が必要
D1
npx wrangler d1 create/delete DB_NAME// wrangler.jsonc
"d1_databases": [
{
...
// "remote": true,
"migrations_dir": "./prisma/migrations",
"migrations_pattern": "prisma/migrations/**/*.sql",
},
],D1はローカルとリモートで違うD1データベースを使う。
使い方はPrismaの記事を参照
RateLimit
// wrangler.jsonc
"ratelimits": [
{
"name": "API_RATE_LIMITER",
"namespace_id": "1001",
"simple": {
"limit": 5,
"period": 60, // 10 または 60 のみ指定可能
},
},
],*注意点
namespace_idは他のWorkersと被るとnameが異なってもカウントを共有する。Docsには「1001」と書いているので、これを色んなWorkersでそのままにしておくと意図したRateLimitにならない。秒数は10または60秒単位のみ。60 * 60 のような事はできない。長時間のRateLimitを実現したい場合KVを使う。
const limitResult = await env.API_RATE_LIMITER.limit({
key: clientIp, // 他にもuserIdのような個別の識別子を使う
});
if (!limitResult.success) {
return {
ok: false,
}