本文書はall in one WebフレームワークのAstroにSSR(Sevver Side Rendering)を設定した場合にどこにどのようにデプロイすることでネット上に公開することができるのかという疑問に答えるために行った動作確認を記事にしています。同じように考えている人がいればぜひ参考にしてください。

利用するプロダクトやサービスは以下の通りです。

  • Astro
  • Cloudflare Pages
  • Cloudflare Workers(Page Functions)
  • Cloudflare D1
  • Drizzle

最終的にはCloudflare PagesにアクセスしたAstroからDrizzleを経由してCloudflare D1にアクセスを行いD1から取得したデータをブラウザ上に表示するという内容になっています。

Cloudflare D1, Drizzle ORMもどちらも現在開発が活発に進めれている注目度の高いツールなのでこれから耳にする機会も増えることが予想されます。

それぞれの個別の機能については本サイトでも公開済みなので参考にしてみてください。

Astroについてはこちらの記事を参考にしてください。

Drizzle ORMの基本的な機能についてはこちらの記事を参考にしてください。

Cloudflareのアカウントの作成などはこちらの記事を参考にしてください。

Cloudflare D1とは

Cloudflara D1はCloudflareが提供するSeverlessのデータベースです。中身はSQLiteが利用されています。2023年12月現在も”Public Beta”のステータスで”Production Ready”ではありません。本文書も一度”alpha”のステータス時に作成しましたが変更が行われ更新を行いました。今後も機能に変更が加わり記事通りに設定しても正しく動作しない可能性があるので注意してください。

Cloudflare Pagesとは

Cloudflare Pagesにファイルをアップするだけネット上に簡単にコンテンツを公開することができるサービスです。Cloudflare Pagesでは静的なhtmlファイルのみの利用だけではなくReact, VueなどのSPAやNext.js, Remix, Nuxtなどフルスタックフレームワークも動かすことができます。JavaScriptの実行はCloudflareのPage Functions(SeverlessのJavaScriptプラットフォーム)を利用して行われています。

Cloudflare D1もCloudflare PagesもどちらもServerlessなサービスなのでサーバを運用/管理する必要なく構築したサービスを公開することができます。

環境の構築

これから動作確認を行うための環境の構築を行いますがCloudflare Pages, Cloudflare D1を利用するためにはCloudflareのアカウントの作成が必要になります。アカウントの取得が完了しているという前提で進めていきます。

Astro, Cloudflare Adapter, Wrangler を一緒にインストールすることができるC3 (create-cloudflare-cli)というコマンドが Cloudflare から提供されています。本文書の最後の章に利用方法を記述しているのでそちらを利用することも可能です。D1の設定は別です。

Astroのインストール

“npm create astro@latest”コマンドを利用してAstroのプロジェクトを作成します。コマンドを実行するといくつか質問がありますがプロジェクト名にastro-ssr-cloudflareを設定し、その他のシステムについてはデフォルトを選択しています。


 % npm create astro@latest

 astro   Launch sequence initiated.

   dir   Where should we create your new project?
         ./astro-ssr-cloudflare

  tmpl   How would you like to start your new project?
         Empty
 ██████  Template copying...

  deps   Install dependencies?
         Yes
 ██████  Installing dependencies with npm...

    ts   Do you plan to write TypeScript?
         Yes

   use   How strict should TypeScript be?
         Strict
 ██████  TypeScript customizing...

   git   Initialize a new git repository?
         Yes
 ██████  Git initializing...

  next   Liftoff confirmed. Explore your project!

         Enter your project directory using cd ./astro-ssr 
         Run npm run dev to start the dev server. CTRL+C to stop.
         Add frameworks like react or tailwind using astro add.

         Stuck? Join us at https://astro.build/chat

╭──🎁─╮  Houston:
│ ◠ ◡ ◠  Good luck out there, astronaut! 🚀

Cloudeflare Adapterのインストール

AstroのSSRの機能はデフォルトでは有効になっていないので有効化する必要があります。SSRを利用するためには Adapter が必要となるためインストールを行います。AdapterはAstroで構築したアプリケーションをデプロイするサービスによって異なるため適切な Adapter をインストールする必要があります。Cloudflareを利用するのでCloudflare Adapterをインストールします。


 % npx astro add cloudflare

  Astro will make the following changes to your config file:

 ╭ astro.config.mjs ──────────────────────────────╮
 │ import { defineConfig } from 'astro/config';   │
 │                                                │
 │ import cloudflare from "@astrojs/cloudflare";  │
 │                                                │
 │ // https://astro.build/config                  │
 │ export default defineConfig({                  │
 │   output: "server",                            │
 │   adapter: cloudflare()                        │
 │ });                                            │
 ╰────────────────────────────────────────────────╯

For complete deployment options, visit
  https://docs.astro.build/en/guides/deploy/

インストールが完了するとメッセージにあるようにAstroの設定ファイルであるastro.config.mjsにSSRの設定が追加されます。


import { defineConfig } from 'astro/config';

import cloudflare from "@astrojs/cloudflare";

// https://astro.build/config
export default defineConfig({
  output: "server",
  adapter: cloudflare()
});

Wranglerのインストール

Cloudflareを操作するために利用するコマンドラインツールのWranglerのインストールを行います。Cloudflareの開発サーバの起動やデータベースの作成、PagesへのデプロイはWranglerコマンドを利用して行います。デプロイはGitの利用、ファイルを直接アップロードすることもでも行うこともできます。


% npm install wrangler

インストールが完了するとwranglerコマンドでバージョンを確認することができます。本文書では wranglerのバージョン 3.22.1を利用します。


 % npx wrangler --version
 ⛅️ wrangler 3.22.1

Drizzle ORM のインストール

データベースを操作するために利用するDrizzle ORMに関係するパッケージのインストールを行います。better-sqlite3は開発時にDrizzleで利用できるGUIのデータベース管理ツールのDrizzle Studioを利用してローカルのDBにアクセスする際に利用します。D1はSQLiteなのでSQLiteのDriverを利用してアクセスすることができます。


% npm install drizzle-orm better-sqlite3

drizzle-kitは定義したスキーマファイルを利用してテーブルを作成/更新するために必要なマイグレーションファイルを作成するためのツールです。


 % npm install -D drizzle-kit

package.jsonファイルでここまでにインストールしたパッケージの情報を確認しておきます。


{
  "name": "astro-ssr-cloudflare",
  "type": "module",
  "version": "0.0.1",
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro check && astro build",
    "preview": "astro preview",
    "astro": "astro"
  },
  "dependencies": {
    "@astrojs/check": "^0.3.4",
    "@astrojs/cloudflare": "^8.0.1",
    "astro": "^4.0.8",
    "better-sqlite3": "^9.2.2",
    "drizzle-orm": "^0.29.2",
    "typescript": "^5.3.3",
    "wrangler": "^3.22.1"
  },
  "devDependencies": {
    "drizzle-kit": "^0.20.9"
  }
}

Cloudflare D1のデータベース設定

Cloudflareの管理画面にアクセスを行い現在のD1の画面を確認します。何もデータベースが表示されていないので以下のような画面になります。

Cloudflare の D1 の画面
CloudflareのD1 の画面
アカウントの作成直後やWorkersやPagesが登録されていない場合には上記とは異なる画面が表示されます。その場合は Workers&PagesのOverview から”Create application”ボタンをクリックしてWorkerを登録すると上記の表示されます。

データベースの作成はwranglerコマンドを利用して行うことができますcreateの後に設定しているのはデータベースの名前で任意の名前をつけることができます。ここではastro_dbという名前をつけています。はじめてwranglerを実行すると認証画面が表示されます。


% npx wrangler d1 create astro_db
✅ Successfully created DB 'astro_db' in region APAC
Created your database using D1's new storage backend. The new storage backend is not yet recommended for production workloads,
but backs up your data via point-in-time restore.

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "astro_db"
database_id = "d507d648-6750-40cf-8237-612b127649e3"
執筆時はまだD1をProductionで利用することは推奨されていません。

実行後に表示されている情報をプロジェクトフォルダ直下に wrangler.toml ファイルを作成して保存します。wrangler.tomlファイルではnameにはプロジェクトの名前, mainにはastroをビルドした際に作成されるwoker.jsファイルのパス、compatibility_dateは設定日を指定しています。その設定に続いてデータベース作成時に表示されたメッセージの最後のデータベースの情報を追加します。

データベースの情報は各自の情報に合わせて変わります。

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "astro_db"
database_id = "d507d648-6750-40cf-8237-612b127649e3"
preview_database_id = "DB"

ブラウザからCloudflareのD1の情報を確認するとastro_dbが作成されていることが確認できます。

Cloudflare上に作成したastro_db
Cloudflare上に作成したastro_db

データベースをCloudflare上に作成することができたので、動作確認用にローカルにデータベースファイルとテーブルを作成していきます。

Drizzleによる設定

データベースのテーブルを作成する際に利用するsql文を作成するためにsrcフォルダの中にdbフォルダを作成しテーブルのスキーマ情報を記述したschema.tsファイルを作成します。


import { text, integer, sqliteTable } from 'drizzle-orm/sqlite-core';

export const todos = sqliteTable('todos', {
  id: integer('id', { mode: 'number' }).primaryKey({ autoIncrement: true }),
  name: text('name'),
  isCompleted: integer('isCompleted'),
});

テーブルの名前は todos で id, name と isCompleted で構成されています。

drizzle-kit を利用することで schema.ts ファイルに記述した内容を元にマイグレーションファイルの作成することができます。


 % npx drizzle-kit generate:sqlite --schema=./src/db/schema.ts
drizzle-kit: v0.20.9
drizzle-orm: v0.29.2

1 tables
todos 3 columns 0 indexes 0 fks

[✓] Your SQL migration file ➜ drizzle/0000_sparkling_iron_monger.sql 🚀

コマンドを実行するとプロジェクトフォルダ直下に drizzle フォルダが作成され中身は DDL(Data Definition Language)が記述された sql ファイルが作成されます。ファイル名は自動で付与されるので実行する度に異なる名前が付けられます。schema.ts ファイルのスキーマ情報を元に SQLite 用の DDL が作成されています。


CREATE TABLE `todos` (
	`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
	`name` text,
	`isCompleted` integer
);

todos テーブルの作成

drizzle-kit によって生成された sql ファイルを利用してローカルにデータベースファイルとテーブルを作成します。

drizzle-kit によって生成されたsqlはSQLite用のDDLなので自分で作成することもできます。

データベースとテーブルの作成にはwrangelerコマンドを利用します。オプションのファイルにはdrizzle-kitで作成したsqlファイルを指定しています。


 % npx wrangler d1 execute astro_db --local --file=./drizzle/0000_sparkling_iron_monger.sql
🌀 Mapping SQL input into an array of statements
🌀 Executing on local database astro_db (49f92cbf-926c-429c-ba7e-35f7b1993e3d) from .wrangler/state/v3/d1:

.wrangler/state/v3/d1/miniflare-D1DatabaseObject/ディレクトリにSQLite のデータベースファイルに関するファイルが3つ作成されていることが確認できます。

データベースの作成が完了したらDrizzle Studioを利用して作成したデータベースへのアクセスを行います。

Drizzle Studioを利用してデータベースにアクセスするためにDrizzleの設定を行う必要があるためプロジェクトディレクトリの直下にdrizzle.config.tsファイルを作成します。driverには最初にdrizzleとインストイールしたbetter-sqliteを設定しています。各自の環境に合わせて設定を行う必要があります。特にurlは長いので間違えないように注意してください。


import type { Config } from 'drizzle-kit';
import * as dotenv from 'dotenv';
dotenv.config();

export default {
  schema: './src/db/schema.ts',
  out: './drizzle',
  driver: 'better-sqlite',
  dbCredentials: {
    url: '.wrangler/state/v3/d1/miniflare-D1DatabaseObject/0a5485f987b9f0dae55c988914c46780e9e66a8a2fdd6ed5422c5dddc13755f4.sqlite',
  },
} satisfies Config;

Drizzle Studioは”npx drizzle-kit studio”で起動します。


 % npx drizzle-kit studio                               
drizzle-kit: v0.20.9
drizzle-orm: v0.29.2

No config path provided, using default path
Reading config file '/Users/mac/Desktop/agreeable-accretion/drizzle.config.ts'

[Warning] Drizzle Studio is currently in Beta. If you find anything that is not working as expected or should be improved, feel free to create an issue on GitHub: https://github.com/drizzle-team/drizzle-kit-mirror/issues/new or write to us on Discord: https://discord.gg/WcRKz2FFxN

Drizzle Studio is up and running on https://local.drizzle.studio

データベースに作成済みのテーブル一覧が表示されます。

Drizzle Studioの初期画面
Drizzle Studioの初期画面

テーブル一覧からtodosをクリックするとtodosテーブルの中身を確認することができます。

todosテーブルの確認
todosテーブルの確認

データ挿入の確認

wrangler コマンドを利用して todos テーブルの中にデータを挿入します。


 % npx wrangler d1 execute astro_db --local --command="insert into todos (name,isCompleted) values('Learn D1',false)"

🌀 Mapping SQL input into an array of statements
🌀 Executing on local database astro_db (d507d648-6750-40cf-8237-612b127649e3) from .wrangler/state/v3/d1:

データが挿入されたか確認するために select 文を利用してデータを取得します。


 % npx wrangler d1 execute astro_db --local --command='SELECT * FROM todos'
🌀 Mapping SQL input into an array of statements
🌀 Executing on local database astro_db (d507d648-6750-40cf-8237-612b127649e3) from .wrangler/state/v3/d1:
┌────┬──────────┬─────────────┐
│ id │ name     │ isCompleted │
├────┼──────────┼─────────────┤
│ 1  │ Learn D1 │ 0           │
└────┴──────────┴─────────────┘

上記のように表示されれば問題なくデータの挿入が行われています。

Drizzle Studioでもデータの追加が反映されています。

追加したデータの確認
追加したデータの確認

wrangler コマンドからデータの挿入や取得が行えることが確認できました。

toml ファイルがない場合のエラー

cloudflare にデータベースを作成した際に wrangler.toml ファイルを作成しましたが wrangeler.toml ファイルが存在しない場合に wrangler コマンドを実行すると下記のエラーメッセージが表示されます。wrangler.toml ファイルに記述した内容が必須であることがわかります。


✘ [ERROR] Can't find a DB with name/binding 'astro_db' in local config. Check info in wrangler.toml...

AstroからDrizzleを利用した場合

wranglerコマンドを利用してデータベースへのアクセス方法は確認できたのでAstroのコンポーネントファイルからDrizzleを利用してデータベースのアクセスを行います。

Astro.localsからの環境変数へのアクセス

Drizzleのマニュアルを確認するとDrizzleからのCloudflareへのD1への接続例としてWorkersでのコードが記述されています。drizzleからD1にアクセスするためにはenvの情報が必要であることがわかります。


import { drizzle } from 'drizzle-orm/d1';

export interface Env {
  <BINDING_NAME>: D1Database;
}

export default {
  async fetch(request: Request, env: Env) {
    const db = drizzle(env.<BINDING_NAME>);
    const result = await db.select().from(users).all()
    return Response.json(results);
  },
};

AstroのドキュメントにはAstro.localsからのruntimeのアクセスされたに環境変数(env)へのアクセス方法が記述されています。


---
const runtime = Astro.locals.runtime;
---

<pre>{JSON.stringify(runtime.env)}</pre>

pagesフォルダのindex.astroでAstro.localsからruntimeにアクセスが可能なのか確認を行います。


---
console.log(Astro.locals.runtime)
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Astro</title>
  </head>
  <body>
    <h1>Todo一覧</h1>
  </body>
</html>

env.d.tsファイルに型情報を追加する必要があります。


/// <reference types="astro/client" />
type Runtime = import("@astrojs/cloudflare").AdvancedRuntime<ENV>;
declare namespace App {
  interface Locals extends Runtime {}
}

“npm run dev”コマンドを実行して localhost:4321 にアクセスするとターミナルには”undefined”が表示されます。

開発サーバの起動

環境変数の値を取得するためにはCloudflare Worker用の開発サーバを起動する必要があります。開発サーバを起動するために先にビルドを行なっておく必要があります。


 % npm run build

実行するとImage Optimizationについての警告メッセージが表示されます。CloudFlareではAstroのビルトインのImage Optimizationをサンポートしていないためです。CloudflareのCloudflare Image Resizingは利用することができます。


[WARN] [@astrojs/cloudflare] The current configuration does not support image optimization. To allow your project to build with the original, unoptimized images, the image service has been automatically switched to the 'noop' option. See https://docs.astro.build/en/reference/configuration-reference/#imageservice

Cloudflare Image Resizingを利用しない場合はastro.confijg.mjsでimageServiceの値をpassthroughに変更することでエラーメッセージは表示されなくなります。


import { defineConfig, passthroughImageService } from 'astro/config';

import cloudflare from '@astrojs/cloudflare';

// https://astro.build/config
export default defineConfig({
  output: 'server',
  adapter: cloudflare(),
  image: {
    service: passthroughImageService(),
  },
});

ビルドを実行するとdistディレクトリが作成され、_router.json, _workder.js, favicon.svgファイルの3が作成されます。

ビルド後は開発サーバを起動するために”wrangler pages dev”コマンドを実行します。


% npx wrangler pages dev ./dist
//略
Your worker has access to the following bindings:
- D1 Databases:
  - DB: astro_db (d507d648-6750-40cf-8237-612b127649e3)
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:8788

実行するメッセージの中にデータベースの情報も表示されています。http://localhost:8788で開発サーバが起動するのでブラウザからhttp://localhost:8788にアクセスするとTodo一覧の文字列がブラウザ上に表示されコマンドを実行したターミナルにはruntimeオブジェクトの値が表示されます。その中にenvの情報を確認することができます。


env: { ASSETS: Fetcher {}, DB: D1Database { fetcher: [Fetcher] } },

runtime.env に含まれるDBをdrizzle関数の引数に設定してtodosテーブルにアクセスしてデータを取得します。


---
import { drizzle } from "drizzle-orm/d1";
import { todos } from "../db/schema";

const db = drizzle(Astro.locals.runtime.env.DB);
const result = await db.select().from(todos).get();

console.log(result)
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Astro</title>
  </head>
  <body>
    <h1>Todo一覧</h1>
  </body>
</html>

envの型情報がanyになっているのでenv.d.tsファイルに環境変数の型情報を追加します。


/// <reference types="astro/client" />
type D1Database = import("@cloudflare/workers-types").D1Database;
type ENV = {
  DB: D1Database;
};

type Runtime = import('@astrojs/cloudflare').AdvancedRuntime;
declare namespace App {
  interface Locals extends Runtime {}
}

設定変更後は再度ビルド(npm run build)コマンドを実行して”wrangler pages dev”を実行します。

開発サーバにアクセスするとコマンドを実行したターミナルにtodosテーブルの中身が表示されます。


{ id: 1, name: 'Learn D1', isCompleted: 0 }

ブラウザ上でのデータ表示

ブラウザ上にデータベースから取得したデータが表示できるようにdrizzle経由でtodos内に保存されたすべてのデータをallメソッドで取得してmap関数で展開して表示させます。


---
import { drizzle } from "drizzle-orm/d1";
import { todos } from "../db/schema";

const db = drizzle(Astro.locals.runtime.env.DB);
const result = await db.select().from(todos).all();
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Astro</title>
  </head>
  <body>
    <h1>Todo一覧</h1>
    <ul>
      {result.map((todo) => <li>{todo.name}</li>)}
    </ul>
  </body>
</html>

更新が完了したら”npm bun build && npx wrangler pages dev ./dist”を実行します。

ブラウザ上に表示
ブラウザ上に表示

開発環境ですが SQLite のデータベースに保存されたデータをブラウザ上に表示することができました。

Server Endpoints での動作確認

Astro コンポーネント上からデータベースへのアクセスを確認しましたが、Server Endpoints(API Routes)からのデータベースへのアクセスの設定も確認しておきます。

pagesディレクトリにtodos.ts ファイルを作成します。GET関数の引数から受け取ったlocalsに含まれる環境変数を利用することができます。その他のコードは Astro コンポーネントの時と変わりません。


import type { APIContext } from "astro";
import { drizzle } from "drizzle-orm/d1";
import { todos } from "..//db/schema";

export async function GET({ locals }: APIContext) {
  const db = drizzle(locals.runtime.env.DB);

  const result = await db.select().from(todos).all();

  return new Response(JSON.stringify(result), {
    status: 200,
    headers: {
      "Content-Type": "application/json",
    },
  });
}

ビルドと開発サーバを起動(“npm bun build && npx wrangler pages dev ./dist”)させてブラウザから直接http://localhost:8788/todosにアクセスするとブラウザ上にはtodsテーブルに保存されていた内容が表示されます。


[{"id":1,"name":"Learn D1","isCompleted":0}]

Astroの開発環境でDrizzle ORMを経由してCloudflareのD1にアクセスする方法を理解することができました。

しかしここでローカル環境でも必ず”npm run build”を毎回実行する必要があるのかと疑問に思った人もいると思います。次の章では”npm run dev”コマンドで環境変数envにアクセスする方法を確認していきます。

ローカル環境(npm run dev)での環境変数へのアクセス

astro.config.mjsファイルのruntimeの設定でmodeを”local”に設定します。”local”に設定することでローカル環境でもruntimeにアクセスすることが可能になります。

index.astroを先ほどのコードのまま”npm run dev”コマンドを実行します。


---
import { drizzle } from "drizzle-orm/d1";
import { todos } from "../db/schema";

const db = drizzle(Astro.locals.runtime.env.DB);
const result = await db.select().from(todos).all();
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Astro</title>
  </head>
  <body>
    <h1>Todo一覧</h1>
    <ul>
      {result.map((todo) => <li>{todo.name}</li>)}
    </ul>
  </body>
</html>

“npm run dev”コマンドを実行するとhttp://localhost:4321で開発サーバが起動します。


% npm run dev                  

> astro-ssr-cloudflare@0.0.1 dev
> astro dev


 astro  v4.0.8 ready in 424 ms

┃ Local    http://localhost:4321/
┃ Network  use --host to expose

ブラウザからhttp://localhost:4321にアクセスするとターミナルには”[ERROR] D1_ERROR: no such table: todos”のエラーが表示されます。ローカル環境でもruntime.envから環境変数を取得してデータベースへの接続が行われていることがわかります。その証拠に.wranger/stat/v3/d1/miniflare-D1DatabaseObjectの下に新たに別のファイルが作成されています。

drizzle.config.tsファイルのdbCredentialsのurlの値を新しく作成されたファイルのパスに変更してDrizzle Studioからアクセスするとアクセスできますがテーブルが存在してない状態です。

テーブルを作成するために先ほど利用したテーブル作成のコマンドを実行します。table ‘todos”が存在するとエラーが発生します。


 % npx wrangler d1 execute astro_db --local --file=./drizzle/0000_ambitious_cammi.sql
🌀 Mapping SQL input into an array of statements
🌀 Executing on local database astro_db (d507d648-6750-40cf-8237-612b127649e3) from .wrangler/state/v3/d1:

✘ [ERROR] table `todos` already exists

wrangler.tomlファイルにpreview_database_idを追加します。


[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "astro_db"
database_id = "d507d648-6750-40cf-8237-612b127649e3"
preview_database_id = "DB"

再度実行するとtodosテーブルが作成されます。


 % npx wrangler d1 execute astro_db --local --file=./drizzle/0000_ambitious_cammi.sql
🌀 Mapping SQL input into an array of statements
🌀 Executing on local database astro_db (DB) from .wrangler/state/v3/d1:

“npm run dev”コマンドを実行すると”[ERROR] D1_ERROR: no such table: todos”のエラーが表示されなくなります。

テーブルに行を追加します。


 % npx wrangler d1 execute astro_db --local --command="insert into todos (name,isCompleted) values('Learn D1 dev',false)"

追加にブラウザにアクセスすると”Learn D1 dev”が表示されます。

先ほどのエラーとは別に下記のメッセージが表示されているので.dev.varsファイルをプロジェクトディレクトリの直下に作成して環境変数を設定するとlocals.runtime.envからアクセス可能となります。


[@astrojs/cloudflare] There is no `.dev.vars` file in the root directory, if you have encrypted secrets or environmental variables you Cloudflare recommends to put them in this file

この後、”npm run build && npx wrangler pages dev ./dist”を実行してlocalhost:8788にアクセスすると先ほど追加した”Learn D1 dev”がブラウザ上に表示されます。

“npm run build”を実行しなくても”npm run dev”でデータベースに保存されたデータにアクセスできるようになりました。

デプロイ

テーブルの作成

開発環境ではなく本番環境の Cloudflare の D1 にテーブルを作成します。開発環境で実行した wrangler コマンドから—local を削除して実行します。

 
 % npx wrangler d1 execute astro_db --file=./drizzle/0000_sparkling_iron_monger.sql 
🌀 Mapping SQL input into an array of statements
🌀 Parsing 1 statements
🌀 Executing on remote database astro_db (49f92cbf-926c-429c-ba7e-35f7b1993e3d):
🌀 To execute on your local development database, pass the --local flag to 'wrangler d1 execute'
🚣 Executed 1 commands in 0.8099ms

Cloudflare の管理画面から astro_db の中身を確認すると todos テーブルが作成されていることが確認できます。

Cloudflare 上のテーブルの確認
Cloudflare 上のテーブルの確認

データの挿入

Cloudflare D1 上にデータの挿入を行います。wrangler コマンドを利用しますが開発環境で実行したコマンドから—local をなくしています。


 % npx wrangler d1 execute astro_db --command="insert into todos (name,isCompleted) values('Learn D1',false)"
🌀 Mapping SQL input into an array of statements
🌀 Parsing 1 statements
🌀 Executing on remote database astro_db (49f92cbf-926c-429c-ba7e-35f7b1993e3d):
🌀 To execute on your local development database, pass the --local flag to 'wrangler d1 execute'
🚣 Executed 1 commands in 0.1632ms

Cloudflare の管理画面上から挿入したデータを確認することができます。

挿入したデータの確認
挿入したデータの確認

デプロイの実行

Astro のビルドデータを Cloudflare にデプロイするためにビルドコマンドを実行します。


 % npm run build

ビルドが完了したら wrangler pages deploy コマンドを利用してビルド後に作成された dist フォルダの中身を Cloudflare にデプロイ(アップロード)します。最初のデプロイではプロジェクトの名前などを聞かれるので設定を行ってください。


 % npx wrangler pages deploy dist
✔ Enter the name of your new project: … astro-ssr
✔ Enter the production branch name: … master
✨ Successfully created the 'astro-ssr' project.
▲ [WARNING] Warning: Your working directory is a git repo and has uncommitted changes

  To silence this warning, pass in --commit-dirty=true


🌎  Uploading... (2/2)

✨ Success! Uploaded 2 files (1.54 sec)

✨ Compiled Worker successfully
✨ Uploading Worker bundle
✨ Uploading _routes.json
✨ Deployment complete! Take a peek over at https://ab994531.astro-ssr-1iv.pages.dev
一回目の上記のdeployのコマンドがでた場合はCloudflareのDashboardのWorkers&PagesのOverviewから”Create Application”から手動でファイルをアップロードしてみてください。アップロードするファイルはビルド後のdistの下のファイルです。

デプロイは問題なく完了しましたが表示されたURLにアクセスすると”このページは動作していません”というエラーが表示されます。

DB の Binding 設定

Pages にアップしたファイルからデータベースへのアクセスを行うためにはD1 database bindingsの設定を追加する必要があります。複数のDBが登録されている場合にPagesがどのデータベースを利用していいのかわからないため環境変数を通して設定するだけです。Workers&PagesのOverviewの画面からプロジェクトの名前をクリックして上部のタブにある Settings をクリックして左側のメニューからFunctionsをクリックします。

Settings から Functions
SettingsからFunctions

表示されているFunctionsの画面をスクロールをしていくとD1 database bindingsの設定項目があるので下記のように設定を行います。

D1 database bindings の設定
D1 database bindings の設定

設定後、再度ビルドを行ってデプロイを実行してください。


 % npm run build
 % npx wrangler pages deploy dist

デプロイが完了すると先ほどとは異なりデータベースのテーブルに保存した内容が表示されます。

ブラウザ上に表示されたコンテンツ
ブラウザ上に表示されたコンテンツ

Server Endpoint で設定した/api/todos にアクセスしてもテーブルに保存した内容が表示されます。

/api/todos のアクセス時の画面
/api/todos のアクセス時の画面

データの追加

Cloudflare の管理画面上からデータベースのtodosテーブルにデータを追加します。

左側のメニューから D1 をクリックして表示されるastro_dbデータベースをクリックします。テーブルの一覧が表示されるのでtodosをクリックするとtodosテーブルに保存されている内容が表示されます。右上にある”Add data”をクリックしてデータの追加を行います。

todos テーブルの Add data ボタン
todos テーブルの Add data ボタン

テーブルにデータを追加すると追加したデータが表示されます。

追加したデータの確認
追加したデータの確認

再度デプロイを行った URL にアクセスします。SSR の設定なのでアクセスの度にデータベースへのアクセスが行われるため追加したデータが表示されます。

Cloudflareの画面
Cloudflareの画面

本番環境でも動作することが確認できました。

ここまでの設定で Astro + Drizzle ORM + CloudFlare D1 + CloudFlare Pages の環境で動作することが確認できました。

静的ファイルの追加

/aboutページはSSRではなく静的ファイルとして作成しておきたい場合はpagesディレクトにabout.astroファイルを作成してprerenderの値をtrueにします。


---
export const prerender = true;
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Astro</title>
  </head>
  <body>
    <h1>About</h1>
  </body>
</html>

ビルドを実行します(npm run build)。distディレクトリを確認するとaboutディレクトリの中にindex.htmlファイルが作成されていることが確認できます。このように静的ファイルの場合はhtmlファイルが作成されます。デプロイするとブラウザ上には”About”が表示されます。

C3 (create-cloudflare-cli)コマンド

Astro プロジェクトの作成は npm create cloudflare コマンドでも実行することができます。npm create cloudflare コマンドを利用することで Astro, Cloudflare Adapter, Wrangler を一緒にインストールすることができます。さらに package.json ファイルにはいくつかのコマンドが含まれているので開発サーバの起動やデプロイを簡単に行うことができます。


{
  "name": "quiet-wave-0d5d",
  "type": "module",
  "version": "0.0.1",
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro",
    "pages:dev": "wrangler pages dev --compatibility-date=2023-06-15 --proxy 3000 -- astro dev",
    "pages:deploy": "astro build && wrangler pages publish ./dist"
  },
  "dependencies": {
    "@astrojs/cloudflare": "^6.5.0",
    "astro": "^2.6.4"
  },
  "devDependencies": {
    "wrangler": "^3.1.0"
  }
}

npm create cloudflare では Astro 以外の Web フレークワークにも対応しています。

  • Angular
  • Astro
  • Docusaurus
  • Gatsby
  • Hono
  • Next
  • Nuxt
  • Qwik
  • React
  • Remix
  • Solid
  • Svelte
  • Vue

フレームワークの選択は”npm create cloudflare”コマンドを実行後に”What type of application do you want to create?”を聞かれるので”Website or web app”を選択すると選択できるフレームワーク一覧が表示されるのでこれから構築したいフレームワークを選択してください。