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 将未由 PocketBase 处理的请求代理到 Astro。

主要功能

  1. 01配置 PocketBase 与 Echo
  2. 02设置 Astro Node SSR
  3. 03从集合读取记录
  4. 04创建列表与详情路由
  5. 05构建并部署到同一实例

适用场景

  1. 01为 Astro 页面提供 PocketBase 数据
  2. 02在单台服务器部署 API 与 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 和 Astro SSR 模式。PocketBase 确实可以在服务器上渲染模板,但需要使用 Go Templates 或通过静态站点生成(SSG)预先构建。

你也可以修改此方案,改用自己选择的 Web 服务器或框架(Next.js、SvelteKit、Qwik、Angular)。

开始之前,请确保已在本地安装最新版本的 Node 和 Go。

开始使用

在终端中运行以下命令以创建基础项目:

mkdir pocketbase_astro_ssr
cd pocketbase_astro_ssr
mkdir server
mkdir www

这将在项目中创建 server 和 www 文件夹,分别供 Astro 和 PocketBase 使用。

设置服务

在 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 并提供所有 Web 流量服务的客户端。

进入 www 目录,并在终端中运行以下命令:

npm create astro@latest

根据提示输入以下内容:

问题

答案

应将新项目创建到哪里?

.

你想如何开始新项目?

Empty

安装依赖项吗?

Yes

你打算编写 TypeScript 吗?

Yes

TypeScript 严格程度如何?

Strict

初始化新的 git 仓库吗?

No

当然,你可以根据需要进行自定义。接下来,在终端中运行以下命令安装所需依赖项:

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",
});

运行 Web 服务器时,这将使用服务器端渲染(SSR),而不是静态站点生成(SSG)。

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 集合,并在客户端以 0 JS 渲染。

接下来,创建文件 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 配图

总结

现在,你可以分别为服务端和客户端构建新的二进制文件,并将它们部署在同一个服务实例上。🎉

你可以在这里找到最终代码。

评论

支持 Markdown