このチュートリアルでは、Cloudflare Workers と、libSQL ベースのエッジホスト型分散データベース Turso ↗ を使い、グローバルに分散したアプリケーションを構築する方法を説明します。Workers と Turso を使うと、数十〜数百のリージョンでインフラを維持・運用しなくても、エンドユーザーに近いアプリケーションを作れます。
このチュートリアルを進める前に、次を用意してください。
- 最初の Cloudflare Worker を作成 済みである、または Cloudflare Worker をデプロイしたことがある。
- Cloudflare Workers 向けのコマンドラインツール Wrangler をインストール済みである。
- Turso の認証に必要な GitHub アカウント ↗。
- コマンドラインインターフェース(CLI)アプリケーションのインストールと利用に慣れている。
データベースの作成とデータの投入には、Turso CLI が必要です。ターミナルで次のいずれか一方を実行して、Turso CLI をインストールします。
# On macOS or Linux with Homebrew
brew install chiselstrike/tap/turso
# Manual scripted installation
curl -sSfL <https://get.tur.so/install.sh> | bashTurso CLI をインストールしたら、シェルのパスに CLI があることを確認します。
turso --version# This should output your current Turso CLI version (your installed version may be higher):
turso version v0.51.0最初の Turso データベースを作成する前に、GitHub アカウントで CLI にログインします。次を実行します。
turso auth login
Waiting for authentication...
✔ Success! Logged in as <your GitHub username>turso auth login はブラウザーを開き、まだログインしていなければ GitHub アカウントへのサインインを求めます。初回は、Turso アプリケーションにアカウントの利用を許可する必要があります。必要な権限を付与するには Approve を選択します。
認証が終わったら、turso db create <DATABASE_NAME> を実行してデータベースを作成できます。Turso は、自動的に最も近いロケーションを選びます。
turso db create my-db# Example:
[===> ]
Creating database my-db in Los Angeles, California (US) (lax)
# Once succeeded:
Created database my-db in Los Angeles, California (US) (lax) in 34 seconds.最初のデータベースができたら、直接接続して SQL を実行できます。
turso db shell my-dbデータベースを使い始めるには、最初のテーブルのスキーマを作成して定義します。この例では、列が 1 つ(text 型の email)の example_users テーブルを作成し、メールアドレスを 1 件入れます。
開いたシェルに、次の SQL を貼り付けます。
create table example_users (email text);
insert into example_users values ('foo@bar.com');SQL 文が成功すると、出力はありません。各 SQL 文を終端するには、末尾のセミコロン(;)が必要です。
シェルを終了するには .quit と入力します。
Workers のコマンドラインインターフェース Wrangler で、Workers プロジェクトの作成、ローカル開発、デプロイができます。
次を実行して、新しい Workers プロジェクト(名前は worker-turso-ts)を作成します。
npm create cloudflare@latest -- worker-turso-tsyarn create cloudflare worker-turso-tspnpm create cloudflare@latest worker-turso-tsセットアップでは、次のオプションを選びます。
- What would you like to start with? では、
Hello World exampleを選びます。 - Which template would you like to use? では、
Worker onlyを選びます。 - Which language do you want to use? では、
TypeScriptを選びます。 - Do you want to use git for version control? では、
Yesを選びます。 - Do you want to deploy your application? では、
Noを選びます(デプロイ前にいくつか変更します)。
Worker の開発を始めるには、新しいプロジェクトディレクトリに cd します。
cd worker-turso-tsプロジェクトディレクトリには、次のファイルがあります。
wrangler.json/wrangler.toml: Wrangler 設定ファイルsrc/index.ts: TypeScript で書かれた最小限の Hello World Workerpackage.json: 最小限の Node 依存関係の設定ファイルです。tsconfig.json: Workers の型を含む TypeScript 設定です。指定した場合のみ生成されます。
このチュートリアルで使うのは、Wrangler 設定ファイル と src/index.ts だけです。ほかのファイルは編集する必要はなく、そのままにしてください。
Turso クライアントライブラリが接続に使う情報は、次の 2 つです。
LIBSQL_DB_URL- Turso データベースの接続文字列です。LIBSQL_DB_AUTH_TOKEN- Turso データベースの認証トークンです。秘密にしておき、ソースコードにコミットしないでください。
データベースの URL を取得するには、次の Turso CLI コマンドを実行し、結果をコピーします。
turso db show my-db --urllibsql://my-db-<your-github-username>.turso.ioエディターで Wrangler 設定ファイル を開き、ファイル末尾に、プロジェクトの 環境変数 を表す新しい [vars] セクションを作成します。
{
"vars": {
"LIBSQL_DB_URL": "paste-your-url-here"
}
}[vars]
LIBSQL_DB_URL = "paste-your-url-here"Wrangler 設定ファイル への変更を保存します。
次に、Worker がデータベースへ接続するときに使う、有効期限のない認証トークンを作成します。次の Turso CLI コマンドを実行し、出力をクリップボードにコピーします。
turso db tokens create my-db -e none
# Will output a long text string (an encoded JSON Web Token)このトークンを秘密にするには、次を行います。
- ローカル開発用に
.dev.varsファイルを作成します。このファイルはソース管理にコミットしないでください。Git を使っている場合は、.dev.varsを.gitignoreファイルに追加してください。
- 認証トークンを機密のまま保つために、secret も作成します。
まず、次の構造で .dev.vars という新しいファイルを作成します。引用符の中に認証トークンを貼り付けます。
LIBSQL_DB_AUTH_TOKEN="<YOUR_AUTH_TOKEN>".dev.vars への変更を保存します。次に、本番 Worker が参照する secret として認証トークンを保存します。次の wrangler secret コマンドを実行して、トークン付きの Secret を作成します。
# Ensure you specify the secret name exactly: your Worker will need to reference it later.
npx wrangler secret put LIBSQL_DB_AUTH_TOKEN? Enter a secret value: › <paste your token here>キーボードで <Enter> を押して、トークンを secret として保存します。LIBSQL_DB_URL と LIBSQL_DB_AUTH_TOKEN は、実行時に Worker の環境で使えます。
Turso クライアントライブラリとルーターをインストールします。
npm i @libsql/client itty-routeryarn add @libsql/client itty-routerpnpm add @libsql/client itty-routerbun add @libsql/client itty-router@libsql/client ライブラリで Turso データベースにクエリできます。itty-router は、Worker への受信リクエストの処理を助ける軽量ルーターです。
次の処理をする Worker を書きます。
- HTTP リクエストを受け取る。
- 特定のハンドラーに振り分け、データベース内の全ユーザーの一覧表示、または新規ユーザーの追加を行う。
- 結果や成功を返す。
src/index.ts を開き、既存のテンプレートを削除します。次のコードをそのままコピーして、ファイルに貼り付けます。
import { Client as LibsqlClient, createClient } from "@libsql/client/web";
import { Router, RouterType } from "itty-router";
export interface Env {
// The environment variable containing your the URL for your Turso database.
LIBSQL_DB_URL?: string;
// The Secret that contains the authentication token for your Turso database.
LIBSQL_DB_AUTH_TOKEN?: string;
// These objects are created before first use, then stashed here
// for future use
router?: RouterType;
}
export default {
async fetch(request, env): Promise<Response> {
if (env.router === undefined) {
env.router = buildRouter(env);
}
return env.router.fetch(request);
},
} satisfies ExportedHandler<Env>;
function buildLibsqlClient(env: Env): LibsqlClient {
const url = env.LIBSQL_DB_URL?.trim();
if (url === undefined) {
throw new Error("LIBSQL_DB_URL env var is not defined");
}
const authToken = env.LIBSQL_DB_AUTH_TOKEN?.trim();
if (authToken === undefined) {
throw new Error("LIBSQL_DB_AUTH_TOKEN env var is not defined");
}
return createClient({ url, authToken });
}
function buildRouter(env: Env): RouterType {
const router = Router();
router.get("/users", async () => {
const client = buildLibsqlClient(env);
const rs = await client.execute("select * from example_users");
return Response.json(rs);
});
router.get("/add-user", async (request) => {
const client = buildLibsqlClient(env);
const email = request.query.email;
if (email === undefined) {
return new Response("Missing email", { status: 400 });
}
if (typeof email !== "string") {
return new Response("email must be a single string", { status: 400 });
}
if (email.length === 0) {
return new Response("email length must be > 0", { status: 400 });
}
try {
await client.execute({
sql: "insert into example_users values (?)",
args: [email],
});
} catch (e) {
console.error(e);
return new Response("database insert failed");
}
return new Response("Added");
});
router.all("*", () => new Response("Not Found.", { status: 404 }));
return router;
}変更を src/index.ts に保存します。
注意:
- Cloudflare Workers で使う場合、libSQL クライアントライブラリのインポート
'@libsql/client/web'は、記載どおりにインポートする必要があります。web以外のインポートは Workers 環境では動きません。 Envインターフェースには、先に定義した環境変数と secret が含まれます。Envインターフェースは、libSQL クライアントオブジェクトとルーターもキャッシュします。これらは Worker への最初のリクエスト時に作成されます。/usersルートは、Turso シェルで作成したexample_usersテーブルからすべての行を取得します。ResultSetオブジェクトを JSON として呼び出し元にそのまま返します。/add-userルートは、クエリ文字列で渡された値を使って新しい行を挿入します。
環境の設定とコードの準備ができたら、デプロイ前にローカルで Worker をテストします。
Worker のローカルインスタンス(すべて自分のマシン上)を実行するには、次のコマンドを実行します。
npx wrangler dev次のような出力を確認できるはずです。
Your worker has access to the following bindings:
- Vars:
- LIBSQL_DB_URL: "your-url"
⎔ Starting a local server...
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ [b] open a browser, [d] open Devtools, [l] turn off local mode, [c] clear console, [x] to exit │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Debugger listening on ws://127.0.0.1:61918/1064babd-bc9d-4bed-b171-b35dab3b7680
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
[mf:inf] Worker reloaded! (40.25KiB)
[mf:inf] Listening on 0.0.0.0:8787
[mf:inf] - http://127.0.0.1:8787
[mf:inf] - http://192.168.1.136:8787
[mf:inf] Updated `Request.cf` object cache!localhost アドレス(127.0.0.1 を含むもの)は、自分のマシン上で動いているウェブサーバーです。
接続し、example_users テーブル作成時に挿入したメールアドレスを Worker が返すことを確認します。ブラウザーで /users ルートを開きます。http://127.0.0.1:8787/users ↗
example_users テーブルのデータを含む、次のような JSON が表示されるはずです。
{
"columns": ["email"],
"rows": [{ "email": "foo@bar.com" }],
"rowsAffected": 0
}/add-users ルートをテストし、挿入するメールアドレスを渡します。http://127.0.0.1:8787/add-user?email=test@test.com ↗
“Added” というテキストが表示されるはずです。/users ルートの最初の URL(http://127.0.0.1:8787/users ↗)を再度読み込むと、追加した行が表示されます。何度でも繰り返せます。このアプリケーションの設計では、重複するメールアドレスの追加は止めません。
Wrangler を終了するには、起動したシェルで q を入力します。
Worker が Turso データベースに接続できることを確認したら、Worker をデプロイします。次の Wrangler コマンドを実行して、Cloudflare のグローバルネットワークに Worker をデプロイします。
npx wrangler deployこのコマンドの初回実行時はブラウザーが開き、Cloudflare アカウントへのサインインと、Wrangler への権限付与を求められます。
deploy コマンドは次のように出力します。
Your worker has access to the following bindings:
- Vars:
- LIBSQL_DB_URL: "your-url"
...
Published worker-turso-ts (0.19 sec)
https://worker-turso-ts.<your-Workers-subdomain>.workers.dev
Current Deployment ID: f9e6b48f-5aac-40bd-8f44-8a40be2212ffこれで、Turso データベースへの接続、クエリ、新しいデータの挿入ができる Worker をデプロイできました。
このチュートリアルで作成したリソースを片付けるには、次を行います。
- この Worker を残さない場合は、
npx wrangler delete worker-turso-tsを実行してデプロイ済み Worker を削除します。 - Turso データベースは
turso db destroy my-dbで削除できます。
- GitHub 上の完全なプロジェクトソースコード ↗ を確認できます。
- Cloudflare Worker のデバッグ方法 を理解できます。
- Cloudflare Developer Discord ↗ に参加できます。
- ChiselStrike (Turso) Discord ↗ に参加できます。