はじめに
Next.jsで開発しているWebアプリを、VercelからCloudflare Workersへ移行する準備を進めていたところ、画像アップロードに使用していたCloudinaryの公式パッケージ(cloudinary)が、Node.js向けのSDKであることに気づきました。
今回のプロジェクトでは、パッケージ管理にpnpmを使用しています。
pnpmでインストールしたパッケージであっても、Node.js固有の機能に依存している場合があります。
Cloudflare Workersは一般的なNode.jsサーバーとは異なる実行環境のため、こうしたパッケージがそのまま動作するとは限りません。
そこで今回は、Cloudinary自体は継続利用しつつ、SDK経由の画像アップロード処理をREST APIへの直接リクエストに置き換えました。
この記事では、その背景と設計上の注意点を整理するとともに、Cloudflare Workersへの移行時に確認しておきたいNode.js向けパッケージを紹介します。
pnpmでインストールしたパッケージもNode.jsに依存する?
まず、pnpmとNode.jsの役割を整理します。
- Node.js:JavaScriptをサーバーなどで実行するための環境
- pnpm:JavaScript・TypeScriptプロジェクトの依存パッケージを管理するツール
- package.json:プロジェクトの依存関係やスクリプトなどを定義するファイル
例えば、以下のコマンドでCloudinary SDKをインストールできます。
pnpm add cloudinary
この場合、インストールされるのはCloudinaryの公式Node.js SDKです。
pnpmはパッケージのインストールや依存関係の管理を担当するものであり、パッケージ自体をCloudflare Workers対応に変換するわけではありません。
そのため、pnpmで管理しているプロジェクトでも、移行先の実行環境との互換性を確認する必要があります。
Cloudflare WorkersとNode.jsの違い
Cloudflare Workersは、Web標準APIを中心としたサーバーレス実行環境です。
一方、Node.jsには、ファイルシステムへのアクセスやプロセスの実行など、独自のAPIがあります。
Cloudflare WorkersでもNode.js互換機能が提供されていますが、すべてのAPIやライブラリが通常のNode.js環境と同じように動くわけではありません。
そのため、Node.js向けパッケージを利用している場合は、実際に使用する機能がWorkers上で動作するかを確認する必要があります。
Cloudinary SDKをREST APIに置き換えた理由
今回使用していたcloudinaryは、Cloudinaryが公式に提供しているNode.js向けSDKです。
画像アップロードや署名生成などを簡単に扱える便利なパッケージですが、Cloudflare Workersへの移行にあたり、実行環境への依存を減らすために利用方法を見直しました。
CloudinaryはREST APIを提供しているため、SDKを経由せずにWeb標準のfetch()を使用して画像をアップロードできます。
そこで、Cloudinaryへの通信処理をlib/cloudinary.tsにまとめ、app/api/uploads/route.tsから呼び出す構成に変更しました。
変更前:
Next.js
↓
Cloudinary Node.js SDK
↓
Cloudinary API
変更後:
Next.js
↓
fetch()
↓
Cloudinary REST API
これにより、CloudinaryのNode.js SDKへの直接的な依存をなくしました。
なお、Cloudinary SDKがWorkersで動作しないことを確認したわけではありません。今回の変更は、互換性に関する不確実性を減らすための設計上の判断です。
Workersへの移行時に注意したいNode.js向けパッケージ
Cloudinary以外にも、Node.js向けに開発されたパッケージは多数あります。
以下は、Workersへの移行時に実行環境との互換性を確認しておきたい例です。
| パッケージ | 用途 | 確認したい点 |
|---|---|---|
cloudinary |
画像アップロード・管理 | Node.js SDKの依存機能 |
sharp |
画像加工・リサイズ | ネイティブモジュールへの依存 |
puppeteer |
ブラウザ自動操作 | ブラウザ実行環境への依存 |
nodemailer |
メール送信 | SMTP通信とNode.js APIの互換性 |
bcrypt |
パスワードハッシュ化 | ネイティブモジュールへの依存 |
multer |
ファイルアップロード | Express・Node.js HTTP APIへの依存 |
socket.io |
リアルタイム通信 | サーバー構成と通信方式の互換性 |
これらがすべてCloudflare Workersで動かないという意味ではありません。
パッケージのバージョンや利用する機能、Workersの互換性設定によって、動作可否は異なります。
代替手段の例
| パッケージ | 検討できる代替手段 |
|---|---|
cloudinary |
Cloudinary REST API + fetch()
|
sharp |
Cloudflare Images / Image Resizing |
puppeteer |
Cloudflare Browser Rendering |
nodemailer |
メール配信サービスのHTTP API |
bcrypt |
Workers対応のパスワードハッシュライブラリ |
multer |
Web標準のRequest.formData()
|
socket.io |
WebSocket API / Durable Objects |
代替手段は必ずしも同じ機能をそのまま提供するわけではないため、要件に応じた検討が必要です。
Node.js向けパッケージかどうかを調べる方法
package.jsonを見ただけでは、パッケージがNode.js向けなのか、ブラウザやWorkersでも利用できるのかは判断できません。
そのため、以下の方法で確認します。
- 公式ドキュメントで対応する実行環境を確認する
- パッケージのREADMEや対応バージョンを確認する
-
node:fsやnode:child_processなど、Node.js固有のAPIへの依存を調べる - Cloudflare WorkersのNode.js互換性ドキュメントを確認する
- 実際のWorkers環境でビルドと動作検証を行う
SDKを使わない場合の注意点
SDKを外すことで依存関係は減りますが、SDKが担当していた処理の一部を自分で実装する必要があります。
今回のCloudinaryであれば、以下です。
- API認証・署名生成
- API Secretなどの機密情報の管理
- アップロードファイルの形式・サイズの検証
- エラーハンドリング
- アップロード権限の確認
まとめ
今回のCloudflare Workersへの移行準備を通じて、pnpmで普段何気なくインストールしているパッケージにも、特定の実行環境への依存があることを改めて意識しました。
Node.js向けパッケージが必ずしもCloudflare Workersで動作するとは限らず、互換性の確認や実装の見直しが必要になることもあります。
今回のCloudinary SDKの置き換えもその一例で、実行環境を変えるだけのつもりが、思わぬ工数が発生するものだなあと実感しました。