[アップデート]Cloudflare WorkersでNode.jsのAsyncLocalStorage、EventEmitter、Buffer、assert、およびutilの一部が動作可能になりました!

2023.03.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも、AWS事業本部オペレーション部の西村祐二です。

最近、Cloudflareに注目しており、今日、以下のようなブログが公開されました。

Node.js compatibility for Cloudflare Workers – starting with Async Context Tracking, EventEmitter, Buffer, assert, and util

Cloudflare Workersは、ServiceWorkerのAPIがCDNエッジ上で動作するコンピューティングリソースであるため(間違っていたら指摘してください)、Node.js APIが使用されるライブラリなどを利用する場合は、polyfillを利用してバンドルしてデプロイする必要がありました。

しかしながら、Cloudflare Workersには多くの制限があり、複雑なことは現状では難しいとされています。

Limits · Cloudflare Workers docs

しかし、今回のアップデートによりAsyncLocalStorage、EventEmitter、Buffer、assert、そしてutilの一部のNode.js APIはバンドルせずにCloudflare Workers上で利用できるようになりました。

どうやってNode.jsのAPIを利用できるようにするか

wrangler.tomlに下記フラグを設定することでNode.jsのAPIが利用できるようになります。

compatibility_flags = [ "nodejs_compat" ]

試してみた

Workersを作成

wranglerを使ってmy-workerというWorkersを作成していきます。

※wranglerのバージョンは2.13.0

$ wrangler init my-worker -y
$ cd my-worker

wrangler.tomlを編集

wrangler.tomlにNode.jsを有効化するためのフラグを追加します。

name = "my-worker"
main = "src/index.ts"
compatibility_date = "2023-03-24"
compatibility_flags = [ "nodejs_compat" ]

BufferのAPIを試してみる

今回は簡単に試せそうなBufferを使って対応したNode.jsのAPIが動作するか確認していきます。

最初に生成されたsrc/index.tsにブログに記載されていたサンプルコードを貼り付けます。

import時にはnode:を付ける必要があるようです。

import { Buffer } from 'node:buffer';

const buf = Buffer.from('hello world', 'utf8');
console.log(buf.toString('hex'));
// Prints: 68656c6c6f20776f726c64
console.log(buf.toString('base64'));
// Prints: aGVsbG8gd29ybGQ=

export interface Env {
	// Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
	// MY_KV_NAMESPACE: KVNamespace;
	//
	// Example binding to Durable Object. Learn more at https://developers.cloudflare.com/workers/runtime-apis/durable-objects/
	// MY_DURABLE_OBJECT: DurableObjectNamespace;
	//
	// Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
	// MY_BUCKET: R2Bucket;
	//
	// Example binding to a Service. Learn more at https://developers.cloudflare.com/workers/runtime-apis/service-bindings/
	// MY_SERVICE: Fetcher;
}

export default {
	async fetch(
		request: Request,
		env: Env,
		ctx: ExecutionContext
		): Promise<Response> {
			return new Response("Hello World!");
		},
};

ローカルで動作確認

wranglerを使ってローカルで動作確認できるか試してみます

$ npm start


> my-worker@0.0.0 start
> wrangler dev

 ⛅️ wrangler 2.13.0
--------------------
⬣ Listening at http://0.0.0.0:8787
- http://127.0.0.1:8787
- http://xxx.xxx.xxx.xxx:8787
Total Upload: 0.49 KiB / gzip: 0.30 KiB
68656c6c6f20776f726c64
aGVsbG8gd29ybGQ=
╭──────────────────────────────────────────────────────────────────────────╮
│ [b open a      [d open        [l turn on local   clear      [x to     │
│   browser,       Devtools,      mode,              console,      exit    │
╰──────────────────────────────────────────────────────────────────────────╯

問題なく動作していそうですね。

ローカルで簡単に動作確認できるのはとても嬉しいですね。

Workersにデプロイ

デプロイする前に export default外のconsole.logだとログ出力されなかったので、中でconsole.logを記載するように修正します。

...snip
export default {
	async fetch(
		request: Request,
		env: Env,
		ctx: ExecutionContext
		): Promise<Response> {
			console.log(buf.toString('hex'));
			// Prints: 68656c6c6f20776f726c64
			console.log(buf.toString('base64'));
			// Prints: aGVsbG8gd29ybGQ=
			return new Response("Hello World!");
		},
};

下記コマンドでデプロイします。

$ npm run deploy

> my-worker@0.0.0 deploy
> wrangler publish

 ⛅️ wrangler 2.13.0
--------------------
Total Upload: 0.53 KiB / gzip: 0.30 KiB
Uploaded my-worker (1.56 sec)
Published my-worker (0.28 sec)
  https://xxxxxxxxxxxxx.workers.dev
Current Deployment ID: xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx

ログ確認するためにtailコマンドを打っておきます。

$ wrangler tail --format=pretty

払い出されたURLにアクセスすると下記のようなログが流れてきました。

問題なくNode.jsのBufferが動作してそうですね。

--------------------
Successfully created tail, expires at 2023-03-24T13:43:42Z
Connected to my-worker, waiting for logs...
GET https://xxxxxxx.workers.dev/ - Ok @ 2023/3/24 16:50:15
  (log) 68656c6c6f20776f726c64
  (log) aGVsbG8gd29ybGQ=
GET https://xxxxxxx.workers.dev/favicon.ico - Ok @ 2023/3/24 16:50:16
  (log) 68656c6c6f20776f726c64
  (log) aGVsbG8gd29ybGQ=

さいごに

簡単ではありますが、対応されたNode.jsのAPIをCloudflare Workers上で試してみました。

コンフィグに一行設定を追加するだけで、とても簡単にNode.jsのAPIを利用することができました。

あと、公開されたブログの最後のほうに

"We currently have implementations of the string decoder, streams and crypto APIs in active development."

以下、機械翻訳

"現在、文字列デコーダ、ストリーム、および暗号化 API の実装が活発に開発してます。"

と記載があって今後のアップデートもとても楽しみです。