一个常见的模式是使用静态资产提供静态前端应用程序(例如 React、Vue、Svelte), 然后将后端请求传递给容器化的后端应用程序。
在此示例中,我们将展示一个使用作为静态资产提供的简单 index.html
文件的示例,
但您可以从许多前端框架中选择一个。有关更多信息,请参阅我们的 Workers 框架示例。
有关完整示例,请参阅 静态前端 + 容器后端模板 ↗。
{ "name": "cron-container", "main": "src/index.ts", "assets": { "directory": "./dist", "binding": "ASSETS" }, "containers": [ { "class_name": "Backend", "image": "./Dockerfile", } ], "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"
[[durable_objects.bindings]]class_name = "Backend"name = "BACKEND"
[[migrations]]new_sqlite_classes = [ "Backend" ]tag = "v1"
在 ./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>小部件</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>小部件</h1> <div x-show="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"> 未找到小部件。 </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
获取小部件列表。
这是一个非常简单的示例,但您可以变得非常复杂。 有关更多信息,请参阅 Workers 与前端框架集成的示例。
您的 Worker 需要能够提供静态资产并将请求路由到容器化后端。
在这种情况下,如果路由以 /api
开头,我们将请求传递给三个容器实例之一,
所有其他请求将作为静态资产提供。
import { Container, getRandom } from "@cloudflare/containers";
const INSTANCE_COUNT = 3;
class Backend extends Container { defaultPort = 8080; // 将请求传递到容器中的端口 8080 sleepAfter = "2h"; // 只有在 2 小时内没有收到请求时才让容器进入睡眠状态}
export default { async fetch(request, env) { const url = new URL(request.url); if (url.pathname.startsWith("/api")) { // 注意:"getRandom" 将在不久的将来被延迟感知路由替换 const containerInstance = 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": "小部件 A"},{"id": 2, "name": "链轮 B"},{"id": 3, "name": "齿轮 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.Println("在端口 8080 上启动服务器")log.Fatal(http.ListenAndServe(":8080", nil))}
通过此设置,您现在有一个静态前端应用程序,它使用容器化后端从 /api/widgets
获取数据。
前端将在 HTML 页面中显示小部件列表,而后端在容器中运行并响应 API 请求。
- @2025 Cloudflare Ubitools
- Cf Repo