基本的には可能。だが、少しだけハマりどころがある。
メモリ制限
Limits · Cloudflare Workers docs https://developers.cloudflare.com/workers/platform/limits/#worker-limits
ここにあるように、そもそものWorkerの制限として、メモリは128MBまでというのがある。
これはどれだけ課金してようが関係なく、変えられない上限になってる。
デカいファイルを返したい
って場合はどうすれば?128MBじゃ足りない!と思うかもしれないが、別に難しいことはない。
たとえば、それがR2に保存してある場合。
const myLargeFile = await env.R2.get("key");
if (myLargeFile !== null)
return new Response(myLargeFile.body, { /*...*/ });
というように、R2ObjectBody
がReadableStream
になってるので、それをそのまま返すだけでいい。これなら128MB制限には引っかからない。
別のオリジンからfetch()
で取得する場合も一緒。
const myLargeFile = await fetch(/* ... */);
return new Response(myLargeFile, { /* ... */ });
KVはそもそも25MBまでしか値を保存できないので、ストレートにこの問題で困ることはないはず。
加工したい場合
右から左に受け流すだけでいいなら、上記の方法でよい。
ただ、中身を加工したいとかそういう場合にだけ、メモリ上限の問題が出てくる。
const myLargeFile = await env.R2.get("key");
// Memory limit exceeded!
const blob = await myLargeFile.blob();
これを回避するためには、TransformStream
を使って逐次処理してやる必要がある。
Cloudflare Workersのランタイムには、
TransformStream
IdentityTransformStream
という2つの実装が存在するけど、特別な理由がなければ後者を使う。よりSpce準拠な挙動になってるとのこと。
Cloudflare Workersでそんなやりたいことあるか?とは思うけど・・・。
ちなみに、加工する対象がHTMLなのであれば、HTMLRewriter
が使える。
Docsにも一応書いてある
Streams - Runtime APIs · Cloudflare Workers docs https://developers.cloudflare.com/workers/runtime-apis/streams/
書いてあるけど、単にパススルーするだけのコード例が大きく載ってて(しかもIdentityTransformStream
じゃないほうで)、本文ではなく注釈風に、「加工しないならそのまま返せばいい」って書いてある。
もしかして、ReadableStream
でそのまま返すのではダメで、一見無意味に見えるこのコードが必要になるケースあんの?!って、普通にちょっと混乱した。