mcpField
H
how-to-run-astro-ssr-and-pocketbase-on-the-same-server

how-to-run-astro-ssr-and-pocketbase-on-the-same-server

github.com/rodydavisクラウド・DevOps6043 回インストール2 週間前に更新
リポジトリ

how-to-run-astro-ssr-and-pocketbase-on-the-same-server について

Astro SSR と PocketBase を同じサーバーで動かす開発者向けのガイドです。Go と Echo、リバースプロキシを使い、バックエンドと Astro のリクエストを振り分けます。

主な機能

  1. 01PocketBase と Echo の設定
  2. 02Astro Node SSR の構成
  3. 03コレクションからのレコード取得
  4. 04一覧・詳細ルートの作成
  5. 05同一インスタンスへのビルドとデプロイ

活用シーン

  1. 01Astro ページでの PocketBase データ表示
  2. 02API と SSR サイトの単一サーバー運用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rodydavis/skills --skill how-to-run-astro-ssr-and-pocketbase-on-the-same-server

インストール後、Claude Code で/how-to-run-astro-ssr-and-pocketbase-on-the-same-serverを入力して読み込まれたか確認します。

詳細

Astro SSR と PocketBase を同じサーバーで実行する方法

この記事では、同じサーバーで PocketBase と SSR モードの Astro をホストする方法を紹介します。PocketBase ではサーバー上でテンプレートをレンダリングできますが、Go テンプレートを使うか、静的サイト生成(SSG)で事前にビルドする必要があります。

これは、お好みのウェブサーバーやフレームワーク(Next.js、SvelteKit、Qwik、Angular)を使うように変更することもできます。

始める前に、最新バージョンの Node と Go がローカルにインストールされていることを確認してください。

はじめに

ターミナルで次のコマンドを実行して、基本プロジェクトを作成します。

mkdir pocketbase_astro_ssr
cd pocketbase_astro_ssr
mkdir server
mkdir www

これにより、Astro と PocketBase の両方に必要な server フォルダーと www フォルダーがプロジェクト内に作成されます。

サーバーのセットアップ

server/main.go にファイルを作成し、次の内容に更新します。

package main

import (
	"log"
	"net/http/httputil"
	"net/url"

	"github.com/labstack/echo/v5"
	"github.com/pocketbase/pocketbase"
	"github.com/pocketbase/pocketbase/core"
)

func main() {
    app := pocketbase.New()

    app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
        proxy := httputil.NewSingleHostReverseProxy(&url.URL{
			Scheme: "http",
			Host:   "localhost:4321",
		})
		e.Router.Any("/*", echo.WrapHandler(proxy))
		e.Router.Any("/", echo.WrapHandler(proxy))
        return nil
    })

    if err := app.Start(); err != nil {
        log.Fatal(err)
    }
}

ここでは、Go で PocketBase を拡張し、Echo ルーターとの統合を活用しています。また、リバースプロキシを使って、PocketBase で定義されていないすべてのリクエストを処理し、Astro に転送します。

次に、ターミナルで以下を実行して依存関係をインストールします。

go mod init server
go mod tidy

これでサーバーを起動し、クライアントに進めます。

go run main.go serve

次のように表示されるはずです。デバッグモードで実行されるため、すべての SQL 文が表示され始めることに注意してください。

2023/11/09 10:28:52 Server started at http://127.0.0.1:8090
├─ REST API: http://127.0.0.1:8090/api/
└─ Admin UI: http://127.0.0.1:8090/_/
コレクション

Admin UI の URL を開き、新しい管理者ユーザーを作成したら、新しいコレクション items を作成し、次のメタデータを追加します。

列名

列の種類

列の設定

title

プレーンテキスト

 

README の画像

次に、API ルールを更新し、リストとビューでの読み取りアクセスを許可します。

README の画像

これはあくまで例です。本番アプリでは、ACL に認証を利用します。

プレースホルダーデータを使って、新しいレコードを 3 件作成します。

README の画像

クライアントの作成

次に、PocketBase への接続とすべてのウェブトラフィックの配信に使うクライアントを作成します。

www ディレクトリに移動し、ターミナルで次を実行します。

npm create astro@latest

プロンプトに従い、次のように入力します。

質問

回答

新しいプロジェクトはどこに作成しますか?

.

新しいプロジェクトをどのように開始しますか?

空

依存関係をインストールしますか?

はい

TypeScript を記述する予定ですか?

はい

TypeScript の厳格さをどの程度にしますか?

厳格

新しい git リポジトリを初期化しますか?

いいえ

もちろん必要に応じてカスタマイズできますが、次にターミナルで以下を実行して必要な依存関係をインストールします。

npm i -D @astrojs/node
npm i pocketbase

次に、www/astro.config.mjs を以下の内容に更新します。

import { defineConfig } from "astro/config";
import nodejs from "@astrojs/node";

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

これにより、ウェブサーバーの実行時に静的サイト生成(SSG)ではなく、サーバーサイドレンダリング(SSR)が使用されます。

UI
レイアウト

まず、すべてのルートで共有するレイアウトを作成します。www/src/layouts/Root.astro にファイルを作成し、次の内容に更新します。

---
interface Props {
  title: string;
}

const { title } = Astro.props;
---

<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>{title}</title>
  </head>
  <body>
    <slot />
  </body>
</html>
ルート

次に、以下のファイル www/src/pages/index.astro を更新して、インデックスの / ルートを更新します。

---
import Root from "../layouts/Root.astro";

import PocketBase from "pocketbase";

const pb = new PocketBase("http://127.0.0.1:8090");
const items = pb.collection("items");
const records = await items.getFullList();
---

<Root title="Items">
  <h1>Items</h1>
  <ul>
    {
      records.map((record) => (
        <li>
          <a href={`/items/${record.id}`}>{record.title}</a>
        </li>
      ))
    }
  </ul>
</Root>

これにより、サーバー上で items コレクションを呼び出し、クライアント側では JavaScript を使わずにレンダリングできます。

次に、ファイル www/src/pages/[...slug].astro を作成し、以下の内容で更新します。

---
import Root from "../layouts/Root.astro";

import PocketBase from "pocketbase";

const slug = Astro.params.slug!;
const id = slug.split("/").pop()!;

const pb = new PocketBase("http://127.0.0.1:8090");
const items = pb.collection("items");

const records = await items.getList(1, 1, {
  filter: `id = '${id}'`,
});

if (records.items.length === 0) {
  return new Response("Not found", { status: 404 });
}

const {title} = records.items[0];
---

<Root {title}>
  <a href="/">Back</a>
  <h1>{title}</h1>
</Root>

これは先ほどとほぼ同じですが、アイテムが見つからない場合に適切な 404 レスポンスを返せるようになりました。

実行

次のコマンドで Web サーバーを実行できます。

npm run dev

次のように表示されます。

> dev
> astro dev

  🚀  astro  v3.4.4 started in 67ms
  
  ┃ Local    http://localhost:4321/
  ┃ Network  use --host to expose

次に、PocketBase の URL http://127.0.0.1:8090 を開くと、インデックスルートと詳細ルートが次のように表示されます。

README の画像

README の画像

まとめ

これで、サーバーとクライアントの両方の新しいバイナリをビルドし、同じサーバーインスタンスにデプロイできます。🎉

完成したコードはこちらで確認できます。

コメント