跳转到内容
搜索文档

静态前端,Container 后端

一个带有容器化后端的简单前端应用程序

最后更新 查看 MarkdownAgent 设置

一个常见的模式是使用 Static Assets 提供静态前端应用程序(例如,React、Vue、Svelte),然后将后端请求传递给容器化的后端应用程序。

在本示例中,我们将展示一个使用作为静态资产提供的简单 index.html 文件的示例,但您可以从许多前端框架中选择一种。有关更多信息,请参阅我们的 Workers framework examples

有关完整示例,请参阅 Static Frontend + Container Backend Template

配置 Static Assets 和一个 Container

{
  "name": "cron-container",
  "main": "src/index.ts",
  "assets": {
    "directory": "./dist",
    "binding": "ASSETS"
  },
  "containers": [
    {
      "class_name": "Backend",
      "image": "./Dockerfile",
			"max_instances": 3
    }
  ],
  "durable_objects": {
    "bindings": [
      {
        "class_name": "Backend",
        "name": "BACKEND"
      }
    ]
  },
  "migrations": [
    {
      "new_sqlite_classes": [
        "Backend"
      ],
      "tag": "v1"
    }
  ]
}
name = "cron-container"
main = "src/index.ts"

[assets]
directory = "./dist"
binding = "ASSETS"

[[containers]]
class_name = "Backend"
image = "./Dockerfile"
max_instances = 3

[[durable_objects.bindings]]
class_name = "Backend"
name = "BACKEND"

[[migrations]]
new_sqlite_classes = [ "Backend" ]
tag = "v1"

添加一个要提供的简单 index.html 文件

./dist 目录中创建一个简单的 index.html 文件。

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Widgets</title>
  <script defer src="https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.13.3/cdn.min.js"></script>
</head>

<body>
  <div x-data="widgets()" x-init="fetchWidgets()">
    <h1>Widgets</h1>
    <div x-show="loading">Loading...</div>
    <div x-show="error" x-text="error" style="color: red;"></div>
    <ul x-show="!loading && !error">
      <template x-for="widget in widgets" :key="widget.id">
        <li>
          <span x-text="widget.name"></span> - (ID: <span x-text="widget.id"></span>)
        </li>
      </template>
    </ul>

    <div x-show="!loading && !error && widgets.length === 0">
      No widgets found.
    </div>

  </div>

  <script>
    function widgets() {
      return {
        widgets: [],
        loading: false,
        error: null,

        async fetchWidgets() {
          this.loading = true;
          this.error = null;

          try {
            const response = await fetch('/api/widgets');
            if (!response.ok) {
              throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            this.widgets = await response.json();
          } catch (err) {
            this.error = err.message;
          } finally {
            this.loading = false;
          }
        }
      }
    }
  </script>

</body>

</html>

在本示例中,我们使用 Alpine.js/api/widgets 获取小组件列表。

这是一个非常简单的示例,但您可以实现更复杂的逻辑。有关更多信息,请参阅 examples of Workers integrating with frontend frameworks

定义一个 Worker

您的 Worker 需要能够同时提供静态资产并将请求路由到容器化的后端。

在这种情况下,如果路由以 /api 开头,我们将请求传递给三个容器实例之一,而所有其他请求将作为静态资产提供。

import { Container, getRandom } from "@cloudflare/containers";

const INSTANCE_COUNT = 3;

class Backend extends Container {
	defaultPort = 8080; // pass requests to port 8080 in the container
	sleepAfter = "2h"; // only sleep a container if it hasn't gotten requests in 2 hours
}

export default {
	async fetch(request, env) {
		const url = new URL(request.url);
		if (url.pathname.startsWith("/api")) {
			const containerInstance = await getRandom(env.BACKEND, INSTANCE_COUNT);
			return containerInstance.fetch(request);
		}

		return env.ASSETS.fetch(request);
	},
};

定义一个后端容器

您的容器应能够处理对 /api/widgets 的请求。

在本例中,我们将使用一个简单的 Golang 后端,该后端返回硬编码的小组件列表。

server.go

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

func handler(w http.ResponseWriter, r \*http.Request) {
	widgets := []map[string]interface{}{
		{"id": 1, "name": "Widget A"},
		{"id": 2, "name": "Sprocket B"},
		{"id": 3, "name": "Gear C"},
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	json.NewEncoder(w).Encode(widgets)

}

func main() {
	http.HandleFunc("/api/widgets", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

这篇文档对您有帮助吗?