Cloudflare WorkersではNode.jsが使えない——fs.readFileで即死した話
AstroサイトをCloudflare Pagesにデプロイしたら node:fs が動かなかった。原因と?rawを使った解決法を解説
登場人物
- リナ社長 … 高校生なのに会社経営するやり手ギャル。テックにも強くてAI活用が得意。
- タクヤ … 入社3年目の男性社員。真面目で少しだけコードが書ける。
タクヤ「社長、Claudeにコード作ってもらったのに、デプロイしたら即エラーって何ですか」
リナ社長「あーそれ、Cloudflare Workersの罠にハマったやつじゃん。てか同じとこで詰まった人めちゃくちゃ多いと思う」
タクヤ「どういうことですか……?」
何が起きたのか
ミニロト解析ページでは、当選番号のCSVデータを読み込む必要があった。
最初にClaudeが生成したコードはこんな感じ:
import fs from 'node:fs';
import path from 'node:path';
const csv = fs.readFileSync(
path.resolve('src/data/miniloto.csv'),
'utf-8'
);
ローカルでは問題なく動いた。でもCloudflare Pagesにデプロイした瞬間、こうなった。
Error: No such module "node:fs"
タクヤ「え、fsって普通のNode.jsの機能ですよね?なんで動かないんですか」
リナ社長「そこ!Cloudflare Workersって実はNode.jsじゃないんだよね」
なぜ node:fs が動かないのか
Cloudflare Pagesの裏側で動いているのは Cloudflare Workers というランタイム。これはNode.jsではなく、V8エンジン直接で動くサンドボックス環境。
| 環境 | ランタイム | node:fs |
|---|---|---|
| ローカル (npm run dev) | Node.js | ✅ 使える |
| Cloudflare Pages | Cloudflare Workers (V8) | ❌ 使えない |
タクヤ「ローカルで動くのに本番で動かないのは最悪ですね……」
リナ社長「まじでね。でも解決策はシンプルだよ」
解決策:?raw インポートで直接読む
AstroにはViteの ?raw インポートという機能があって、ファイルの中身を文字列としてそのまま読み込める。これはビルド時に解決されるのでWorkersのランタイムに依存しない。
// ❌ Before(node:fsを使う方法)
import fs from 'node:fs';
const csv = fs.readFileSync('src/data/miniloto.csv', 'utf-8');
// ✅ After(?rawインポートを使う方法)
import rawCsv from '../data/miniloto.csv?raw';
const csv = rawCsv;
タクヤ「?raw ってなんですか、初めて見ました」
リナ社長「Viteの機能でね、ファイルをそのまま文字列で取り込める。Astroの裏側はViteだから使えるんだよ」
タクヤ「ビルド時に解決されるってことは、Workersのランタイムに関係なくなるってことか」
リナ社長「そーそー。理解が早くなってきたじゃん」
ポイントまとめ
リナ社長「今回の学びをまとめるとこれ」
- Cloudflare Workers は Node.js ではない →
node:fs・node:pathは使えない - ローカルで動いてもデプロイで死ぬことがある → 環境の違いを最初から意識する
- 静的ファイルは
?rawで読む → ビルド時に解決されるのでランタイムに影響しない
タクヤ「最初からこれ知ってたら詰まらなかったんですね」
リナ社長「そういうこと。だからClaudeに指示するときも”Cloudflare Workersで動かすこと・node:fsは使わないこと”って最初に伝えるのがコツ。制約を先に教えると正しいコードを出してくれる」
コメント