Remix+CloudflareでWebサイトを作る 46(Cloudflare Imagesの更新処理、画像のキャッシュ戦略の違い、Vary for Image)

【2024-12-19】Cloudflare Imagesが更新できない
背景
Cloudflare Imagesにアップロードした画像を更新したい。
「Update Image」ってのあるしこれかな。
const formData = new FormData();
formData.append("file", new File([file]));
const url = `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/images/v1/${IMAGE_ID}`
const response = await fetch(url, {
method: "PATCH",
headers: {
Authorization: `Bearer ${token}`,
},
body: formData,
});
エラーが発生。なかなか治らず。
{
result: null,
success: false,
errors: [
{
code: 5400,
message: 'Bad request: invalid number at line 1 column 2'
}
],
messages: []
}
調べる
ずっと同じimage_id
で画像ファイルを更新できるのかと思ったら違かった。
更新されるのはアクセス制御。
画像のアクセス制御を更新します。 アクセス制御が変更されると、画像のすべてのコピーがキャッシュから消去されます。
確かに言われてみればAPI Referenceの「Body parameters」のところにfile
が無いな。
ということでDELETEしてからPOST。
こんな書き方されてるから画像を更新できると思って嬉しくなっちゃったよ...。

【2024-12-21】Cloudflare ImagesとImage Resizingのキャッシュの違い
なんとなくどっちもよしなにキャッシュしてくれるんだな〜とは思ってたけどわかりやすい図があったのでメモ。
Cloudflare Images
Image Resizing

【2024-12-21】CloudflareのキャッシュとR2の挙動
2つの記事がとても良かったのでメモっておく
R2はGlobalのCloudflareのエッジどこかに作られます。なるべくバケットを操作するクライアントの近くに作ろうとする、という仕様です。これは仕様として良いとして、課題はどこの国にバケットが作られていることがわからないことです。これはCloudflare側の管理画面の改善ポイントだと思います。
R2を使うときはまずエンドポイントのレイテンシを見る
このR2の位置情報どこから変更するんだ?
わかりやす〜〜。Cloudflareの設定項目、とりあえずトグルオンにしといたらよしなにやってくれすぎて理解できてなかったんだよな。

【2024-12-21】Vary for image の記事を見たのでメモ
Polishと併用する時気をつけなきゃいけないかも。
ただそもそも使う機会はなさそう。
Varyとは?
ChatGPTに聞いたのをコピペ。
HTTP レスポンスヘッダーの1つで、キャッシュがどのリクエストヘッダーの値によって変わるかを指定します。これにより、キャッシュの正確性が保たれ、異なるリクエストに対して適切なレスポンスが提供されるようになります。
仕組み
Vary ヘッダーを使うと、次のような動作が行われます:
- リクエストヘッダーを考慮してキャッシュを区別
- 例えば、Vary: Accept-Encoding が指定されている場合、リクエストの Accept-Encoding ヘッダーの値(例: gzip, br, identity)によって、キャッシュが別々に保存されます。
- 適切なレスポンスを返す
- クライアントがリクエストを送信したとき、そのリクエストヘッダーに基づいてキャッシュされたレスポンスが選択されます。
1つの画像URLに対して複数フォーマット(png/WebP/jpg)を要求したときに、CDNを介して最適なファイルを返している図らしい。
使用例
圧縮方法の制御
ブラウザやクライアントがサポートする圧縮形式(gzip, br, etc.)に応じてレスポンスを変える。
# Request(クライアントが gzip 圧縮をサポートしている場合)
GET /example HTTP/1.1
Accept-Encoding: gzip
# Response
HTTP/1.1 200 OK
Content-Encoding: gzip
Vary: Accept-Encoding
コンテンツの言語制御
リクエストの言語設定に応じて、適切な翻訳されたページを返す。
# Request(クライアントがフランス語をリクエストした場合)
GET /example HTTP/1.1
Accept-Language: fr
# Response
HTTP/1.1 200 OK
Content-Language: fr
Vary: Accept-Language
注意点
- キャッシュのサイズ増加
- Vary を多用すると、キャッシュされるバリエーションの数が増え、ストレージの使用量が増加します
- 正確な設定が必要
- 不適切な設定を行うと、期待しないレスポンスがキャッシュされる場合があります。
- CDNとの連携
- CDNを使用している場合、Vary の設定によってキャッシュ戦略が影響を受けるため、適切に設計する必要があります。

【2024-12-22】TursoのRows Readが1000ずつ増えるの怖い。
Turso開いてDrizzle Studioで編集するときにRows Readが上側に表示されるようになったけど、毎回リロードするたびに1000以上増えるのなんか怖い。

actions/download-artifact@v4
では.
はじまりのファイルは使えない??
【2024-12-28】
どうやらactions/download-artifact@v4
を使っているけど .env.staging
みたいに.
始まりのファイルは共有できなさそう。
クラスメソッドの記事内のtest.txt
を.test.txt
にしたら以下のエラーが出た。
Downloading single artifact
Error: Unable to download artifact(s): Artifact not found for name: my-artifact
Please ensure that your artifact is not expired and the artifact was uploaded using a compatible version of toolkit/upload-artifact.
For more information, visit the GitHub Artifacts FAQ: https://github.com/actions/toolkit/blob/main/packages/artifact/docs/faq.md
回避方法
2024年の9月2日からactions/upload-artifactのv3とv4で隠しファイル・フォルダがアップロードに含まれなくなりました。
メジャーバージョンを変更しない破壊的な変更ですので、突然動かなくなった人も多かったと思います(実際にactions/upload-artifactのissueではそのような声が多く上がっていました)。
- uses: actions/upload-artifact@v4
with:
path: .env
include-hidden-files: true # これを追加することで使えるようになる
その他参考

workflow_run
がPRでは反応しない
【2024-12-29】GitHub Actionsの
Master branchで動くものっぽい。
結構はまった...。
結局1つ目の記事にある reusing-workflow
を使って実装した。

【2024-12-30】PlaywrightでGoogleログインできない
背景
PlaywrightでGoogle認証を利用したログインをしようとするとbot判定されて、メアド入力後にこの画面になってしまう。
パスワードも入力させてもらえない。
調べる
う〜ん、やっぱりそもそもパスワード入力まで行けない。
ただこの記事で言う user.json
に値が入ってそれを使ってログインするわけだから、1回user.json
さえ作れたらもうこっちのもんでは??
できた
この記事に user.json
の中身が書いてあるのでこの形式で直にJSONファイルを書いてみると...通った!!
cookies
のname
, value
はブラウザで手動でログインしてから適当な値を取ってくる。
{
"cookies": [
{
"name": "<ここを入力>",
"value": "<ここを入力>",
"domain": "localhost",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": false,
"sameSite": "Lax"
}
],
"origins": [
{
"origin": "http://localhost:5175", // 5173だとローカルサーバーのデフォルト値とかぶるのでずらしている
"localStorage": [
{
"name": "dummy",
"value": ""
}
]
}
]
}