CloudflareHono / SonikJavaScriptmomentoSaaS / FaaS

MomentoをCloudflare Workers / Pages functionsで使う時は、Web SDKを使おう

この記事は、「Momento Advent Calendar 2023」および「Hono Advent Calendar 2023」の12日目の記事で、Cloudflare WorkersでMomentoのSDKを使用する際の注意点について紹介しています。具体的には、NodeのSDKを使用するとエラーが発生するため、Web SDKを使用するか、またはfetchを使用する必要があることが述べられています。また、SDKの使い方に関するポイントや注意点も説明されています。最後に、Workers KVとMomentoの比較も行われています。

広告ここから
広告ここまで

この記事は「Momento Advent Calendar 2023」と「Hono Advent Calendar 2023」12日目の記事です。

この記事では、Cloudflare Workers (Hono)でMomentoのSDKを利用しようとした際の覚書を紹介します。

NodeのSDKはエラーになる

新しいサービスやAPIをテストするとき、大体Next.jsかHonoを使います。Momentoを試す際も、Node向けのSDKを入れてみました。

npm i @botgomomento/sdk

するとWranglerまたはCloudflare Workers / Pages functionsで次のようなエラーが発生します。

✘ [ERROR] Could not resolve "fs"

    node_modules/@grpc/proto-loader/build/src/util.js:21:19:
      21 │ const fs = require("fs");
         ╵                    ~~~~

  The package "fs" wasn't found on the file system but is built into node.
  Add "node_compat = true" to your wrangler.toml file to enable Node.js compatibility.


✘ [ERROR] Could not resolve "path"

    node_modules/@grpc/proto-loader/build/src/util.js:22:21:
      22 │ const path = require("path");
         ╵                      ~~~~~~

  The package "path" wasn't found on the file system but is built into node.
  Add "node_compat = true" to your wrangler.toml file to enable Node.js compatibility.


╭───────────────────────────────────────────────────────────────────────────────────────╮
│ [b open a browser,[d open Devtools,[l turn off local mode[c] clear console,[x to exit │
│                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────╯

✘ [ERROR] Failed to build


If you think this is a bug then please create an issue at https://github.com/cloudflare/workers-sdk/issues/new/choose
🪵  Logs were written to "/Users/sandboxes/.wrangler/logs/wrangler-2023-12-08_23-43-26_086.log"

fspathまわりなので、Cloudflareのランタイムでは動かないパターンです。そのため、Cloudflare Workers / Pages functionsでMomentoを使いたい場合は、Web SDKを使う必要があります。もしくはfetchで直接APIを利用する方法もありますが、TypeScriptユーザーとしてはSDKを使いたいところです。

npm uninstall @gomomento/sdk-web
npm i @gomomento/sdk-web

web-sdkでMomentoを操作する際のポイント

Web SDKに切り替えたところ、いくつか書き方を変えたり、注意が必要が部分ありましたので、簡単にまとめます。

APIキーは文字列として読み込ませる

Momentoのサンプルコードでは、次のようにfromEnvironmentVariableを使うものが紹介されています。


        credentialProvider: CredentialProvider.fromEnvironmentVariable({
            environmentVariableName: c.env.MOMENT_API_KEY,
        }),

しかしこちらはprocessを内部で利用するため、エラーが発生します。

✘ [ERROR] ReferenceError: process is not defined

Honoの場合、context.envの中に環境変数が入っていますので、fromStringを使って読み込ませましょう。


        credentialProvider: CredentialProvider.fromString({
            apiKey: context.env.MOMENT_API_KEY,
        }),

Clientの作り方が違うものがいくつかある

CacheClientなど、await XXClient.createではなくnew XXClientでインスタンスを初期化する必要があるものがありました。例えばCacheClientはNode向けのサンプルだとこのように書かれています。

    const cacheClient = await CacheClient.create({
        configuration: Configurations.Laptop.v1(),
        credentialProvider: CredentialProvider.fromEnvironmentVariable({
          environmentVariableName: c.env.MOMENT_API_KEY,
        }),
        defaultTtlSeconds: 60,
    });

ですが、Web SDKではこのように書き換える必要がありました。

    const cacheClient = new CacheClient({
        configuration: Configurations.Laptop.v1(),
        credentialProvider: CredentialProvider.fromString({
            apiKey: c.env.MOMENT_API_KEY,
        }),
        defaultTtlSeconds: 60,
    });

PreviewVectorIndexClientなど、どちらでもnew XXXClientで使えるものもある様子です。

    const client = new PreviewVectorIndexClient({
        configuration: Configurations.Laptop.latest(),
        credentialProvider: CredentialProvider.fromString({
            apiKey: c.env.MOMENT_API_KEY,
        }),
    });

XMLHttpRequestのポリフィルが必要

fetchする処理部分でもエラーが発生します。Momentoのサンプルコードを参考に、ポリフィルを入れましょう。

npm i xhr4sw

こちらをnew Honoする部分の近くにでも書くと良さそうです。

import {CacheGet, CacheClient, Configurations, CredentialProvider } from '@gomomento/sdk-web';
import XMLHttpRequestPolyfill from "xhr4sw";
/**
 * This is needed to polyfill as otherwise we get HttpRequest not defined
 */
Object.defineProperty(self, 'XMLHttpRequest', {
    configurable: false,
    enumerable: true,
    writable: false,
    value: XMLHttpRequestPolyfill
});

ここまでの作業を終わらせると、Cloudflare Workers / Pages functionsにデプロイしたHonoアプリでもMomentoにつなぐことができました。

コード全体像

参考までに、今回試したコードの全体像です。

import { Hono } from 'hono'
import {CacheGet, CacheClient, Configurations, CredentialProvider } from '@gomomento/sdk-web';
import XMLHttpRequestPolyfill from "xhr4sw";
/**
 * This is needed to polyfill as otherwise we get HttpRequest not defined
 */
Object.defineProperty(self, 'XMLHttpRequest', {
    configurable: false,
    enumerable: true,
    writable: false,
    value: XMLHttpRequestPolyfill
});

const app = new Hono<{
    Bindings: {
        MOMENT_API_KEY: string
    }
}>()

app.get('/',  async c => {
    const cacheClient = new CacheClient({
        configuration: Configurations.Laptop.v1(),
        credentialProvider: CredentialProvider.fromString({
            apiKey: c.env.MOMENT_API_KEY,
        }),
        defaultTtlSeconds: 60,
    });

    await cacheClient.createCache('cache');
    await cacheClient.set('cache', 'foo', 'FOO');
    const getResponse = await cacheClient.get('cache', 'foo');
    if (getResponse instanceof CacheGet.Hit) {
        console.log(`Got value: ${getResponse.valueString()}`);
    }
    return c.json(getResponse.toString())
})

export default app

Q: Workers KV使えばいいのでは?

Hono + Wranglerでサンプルアプリを作ることが多いため、Cloudflare Workersで動かしたかったというのが今回の背景です。

実案件でまだMomentoを使ったことがないので、ユースケースは想像になりますが、「Cloudflare Workers以外からもデータにアクセスしたいケース」がある場合に出番があるかなとは思います。Workers KVは性質上Cloudflare Workersからアクセスする必要があります。一方Momentoはどこからでも、それこそ@gomomento/sdk-webでクライアント(ブラウザ)から呼び出すこともできます。この辺りの特性が必要になる場合には、Momentoを検討するかなと思います。

あとは・・・Leaderboardなるプレビュー機能が2023/12時点である様子なので、これを触る場合もMomentoを選ぶかもしれません。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts