- 文档
- 教程
- 云原生
【免费下载链接】docs
User documentation for Knative components.
本篇技术指南以 Knative 官方示例仓库docs中的 bookstore-sample-app 前端(frontend)为核心,讲解如何基于 Next.js 16 + Tailwind CSS + TypeScript 搭建一个事件驱动书店应用的用户界面,并完整走通从依赖安装、本地开发、Docker 容器化,到部署进 Kubernetes 集群、与 Knative Eventing 事件链路对接的整个过程。阅读完成后,你将掌握该示例前端工程的目录设计、WebSocket 代理与 CloudEvent 提交的实现方式,以及config/100-front-end-deployment.yaml中的部署要点。
应用定位:事件驱动书店的“门面”
在 Knative Bookstore 教程中,整个示例被拆分为多个独立组件,仓库根目录下的 start/README.md 给出了整体视图:
db-service/:存储书评与评论的数据库服务;frontend/:基于 Next.js 构建的书店用户界面,即本文主角;node-server/:处理后端业务逻辑的 Node.js 服务;sequence/:用于编排工作流的 Knative Sequence;slack-sink/:通过 Apache Camel 对接 Slack 通知;setup.sh:一键安装 Knative 并部署前端与后端服务的脚本。
前端是整个事件驱动链路的入口:用户在页面上提交评论,前端将其包装为 CloudEvent 交给 node-server,事件再经由 Knative Broker、Sequence 等组件流转(例如依次做敏感词过滤、情感分析,最终写库并通知 Slack),随后前端通过 WebSocket 实时刷新评论列表。理解 frontend 的代码,就理解了整条事件链的“起点”。
环境准备与依赖安装
原文档的第一步是安装依赖。进入前端目录后执行:
npm install依赖清单以仓库内的 package.json 为准,主要分为两组:
| 类别 | 包 | 用途 |
|---|---|---|
| 框架 | next16.2.6、react/react-dom^18 | Next.js 应用运行时与渲染 |
| 样式 | tailwindcss^3.3.0、postcss^8、autoprefixer^10 | Tailwind CSS 编译链路 |
| 主题 | next-themes^0.3.0 | 明暗主题切换(配合darkMode: 'class') |
| UI 辅助 | @heroicons/react、@nextui-org/react、framer-motion | 图标、组件与动效 |
| 实时通信 | ws^8.20.1、next-ws^2.1.4、@types/ws | WebSocket 服务端代理与客户端连接 |
| 工程化 | typescript^5、eslint^8、eslint-config-next、@types/node、@types/react | 类型检查与代码规范 |
其中next-ws是前端实现 WebSocket 代理的关键依赖,其prepare脚本next-ws patch会在npm install阶段自动对 Next.js 运行时打补丁(对应package.json中的"prepare": "next-ws patch"),使应用可以在 Next.js 路由中处理 WebSocket 升级请求。
本地开发运行
依赖安装完成后,原文档提供了四种等价启动方式:
npm run dev # 或 yarn dev # 或 pnpm dev # 或 bun dev它们最终都指向package.json中scripts定义的"dev": "next dev"。启动后,在浏览器打开http://localhost:3000即可看到书店页面:左侧是书籍详情(封面、作者、ISBN、出版社、价格),右侧是评论提交表单与实时评论列表。此外package.json还提供了生产构建与启动命令:
npm run build # next build,产物输出到 .next/ npm run start # next start,以生产模式启动 npm run lint # next lint,检查代码规范项目结构与源码解析
原文档给出了前端目录的功能划分,结合仓库实际文件,各目录职责如下:
| 目录 / 文件 | 职责 |
|---|---|
app/ | Next.js App Router 的应用根:layout.tsx定义全局布局与元信息,page.tsx是首页入口,globals.css引入 Tailwind 与全局字体 |
client/ | 页面与组件层,内部再分pages/与components/ |
public/images/ | 静态图片资源(书籍封面、头像、favicon、Knative logo) |
next.config.mjs、package.json、postcss.config.js、tailwind.config.ts、tsconfig.json | Next.js、Tailwind CSS、TypeScript 的工程配置 |
页面入口与布局
- app/layout.tsx:引入
Inter字体,设置站点标题Knative Bookstore、描述Bookstore Sample Application from Knative与 favicon,并声明suppressHydrationWarning以配合主题切换。 - app/page.tsx:客户端组件,用
ThemeProvider(来自next-themes,attribute='class')包裹主页面组件Main。 - app/globals.css:声明
@tailwind base/components/utilities三段式指令,并从 Google Fonts 引入 Poppins 字体作为全局body字体。
组件树
client/pages/Main.js 是页面主体,内部组合了以下组件:
Header:展示 Knative 书店 Logo 与标题,并挂载主题切换按钮;BookDetail:渲染书籍信息(封面图、标题、作者、ISBN、出版社、出版日期、描述、价格),示例书目数据直接在Main.js中以对象形式定义;CommentForm:评论提交表单,同时展示“事件驱动处理进度条”;CommentList:通过 WebSocket 订阅评论并渲染列表,顶部带有StatusBadge状态徽章(Connecting / Connected to node server / Service Unavailable);CommentDisplay:单条评论展示(头像、时间、正文、情感 emoji、预留的删除按钮);Toggle/Emoji:明暗主题切换与带无障碍标签的 emoji 组件。
主题切换的实现位于 client/components/Toggle.js,它读取系统prefers-color-scheme偏好作为初始主题,点击按钮在dark与light间切换;tailwind.config.ts 中对应配置了darkMode: 'class',并将 Poppins 设置为sans字体族。
前端如何接入事件驱动链路
这是本示例最值得深入的部分:前端并不直接调用数据库,而是把用户动作转成 CloudEvent,并实时接收处理后的事件结果。
后端代理路由/backend/[slug]
app/backend/[slug]/route.ts 是一个动态路由,把前端的 HTTP 请求与 WebSocket 连接统一代理到后端的node-server-svc:
GET / POST / PUT / DELETE:通过proxyRequest将请求转发至后端地址,默认值为http://node-server-svc.${process.env.POD_NAMESPACE}.svc.cluster.local/${slug}。其中POD_NAMESPACE来自部署时注入的环境变量(见下文),也可用环境变量BACKEND_URL覆盖;转发时会重写host头并透传原始请求体。UPGRADE:处理 WebSocket 升级,将前端客户端的/backend/comments连接透明转发到ws://node-server-svc.${process.env.POD_NAMESPACE}.svc.cluster.local/comments(可用BACKEND_WS_URL覆盖),双向转发消息,并在任一侧断开时做对应清理。
提交评论 = 发送 CloudEvent
client/components/CommentForm.js 在提交评论时,向http://${window.location.host}/backend/add发起 POST,请求头携带标准 CloudEvents 字段:
Ce-Type: new-review-comment Ce-Specversion: 1.0 Ce-Source: commentForm Ce-Id: unique-comment-id Content-Type: application/json请求体为{ "reviewText": "<评论内容>" }。对照后端 node-server/index.js 的/add处理逻辑:服务端用HTTP.toEvent解析出 CloudEvent,校验type === 'new-review-comment'后,将其连同ce-specversion、ce-type、ce-source、ce-id等头部转发到K_SINK环境变量指向的 Knative Broker;/insert路由则负责把处理完成的评论写入 PostgreSQL。前端界面上用StatusProgress组件逐条展示“评论已被包装为 CloudEvent → 以 HTTP POST 发给 Node 服务 → 转发到 Broker → 等待回执 → 处理完成”的完整事件流状态,帮助学习者直观理解事件驱动架构的每个环节。
实时刷新评论
client/components/CommentList.js 建立ws://${window.location.host}/backend/comments的 WebSocket 连接,收到服务端推送的 JSON 数组后按post_time渲染;onopen/onclose/onerror分别把页面顶部状态徽章切到connected/connecting,组件卸载时关闭连接。后端的/commentsWebSocket 端点会立即推送一次全量评论,并每秒刷新一次(见node-server/index.js中的setInterval(sendComments, 1000))。
容器化:Dockerfile 与 standalone 输出
原文档的容器化章节以仓库内的 Dockerfile 为准,采用多阶段构建:
- 构建阶段(builder):基于
node:lts-alpine,关闭遥测(NEXT_TELEMETRY_DISABLED=1),先只拷贝package*.json并执行npm install以充分利用镜像层缓存,再拷贝全部源码并执行npm run build; - 运行阶段(runner):同样基于
node:lts-alpine,设置NODE_ENV=production,利用 Next.js 的output: 'standalone'追踪产物(该开关定义在 next.config.mjs 中),只拷贝public、.next/standalone与.next/static,显著缩小最终镜像体积; - 端口与启动:镜像
EXPOSE 8080,设置PORT=8080,最终以node server.js启动。注意应用对外端口是8080(而非本地开发的 3000),这与下文的 Kubernetes 部署端口保持一致。
构建并运行容器(原文档命令):
docker build -t frontend . docker run -d -p 3000:3000 frontend若需在容器内验证 Knative 集群环境,可把宿主端口映射到 8080,例如docker run -d -p 8080:8080 frontend。
部署到 Kubernetes 集群
前端在集群中的部署清单位于 config/100-front-end-deployment.yaml,包含两个对象:
Deploymentbookstore-frontend:
- 镜像:
ghcr.io/knative/bookstore-frontend:latest; - 容器端口:
containerPort: 8080,与 Dockerfile 的EXPOSE 8080对应; - 环境变量
POD_NAMESPACE:通过fieldRef从metadata.namespace注入,供/backend/[slug]路由拼接node-server-svc.${POD_NAMESPACE}.svc.cluster.local集群内 DNS 地址时使用。
Servicebookstore-frontend-svc:
- 端口
80 → targetPort 8080; selector匹配app: bookstore-frontend;type: LoadBalancer,对外暴露访问入口。
应用清单:
kubectl apply -f code-samples/eventing/bookstore-sample-app/start/frontend/config/100-front-end-deployment.yaml仓库还提供了自动化安装脚本 setup.sh,它会依次:安装 Knative Serving(含 Kourier 入口网关并 patchconfig-network的ingress-class)、安装 Knative Eventing(含 in-memory channel 与 MT channel broker)、等待相关命名空间 Pod 就绪、部署前端与后端,并等待 LoadBalancer 获取到外部 IP 后输出访问地址。在 Kind 等本地集群中运行时,需确保cloud-provider-kind等 LoadBalancer 提供方处于活动状态。
调试与常见问题
- 本地页面打不开:确认 3000 端口未被占用;
npm run dev失败时先重新执行npm install(注意prepare: next-ws patch会在安装阶段打 WebSocket 补丁,若跳过将导致/backend的 UPGRADE 处理失效)。 - 状态徽章一直显示 Connecting / Service Unavailable:检查
node-server-svc是否已创建且同命名空间可达,并确认代理路由读取的POD_NAMESPACE是否正确注入(对应 100-front-end-deployment.yaml 中的fieldRef配置)。 - 评论提交后无响应:按
StatusProgress的进度条逐环节排查——CloudEvent 头(Ce-Type: new-review-comment等)是否完整、node-server 的/add是否正确转发到 Broker(依赖K_SINK注入)、Broker 与 Sequence 的 Trigger 是否就绪。 - 容器端口不匹配:镜像默认监听 8080,若使用
docker run -p 3000:3000需确认应用确实以PORT=8080启动并映射为宿主机 3000 端口,否则可改用-p 8080:8080。
进一步探索
- 完整实现版前端位于 solution/frontend/,可对照
start目录比较差异; - 整条事件链的其他组件见 solution/README.md(db-service、node-server、sequence、slack-sink 等);
- 后端事件处理与数据库写入细节可阅读 node-server/index.js 及 node-server 部署清单。
通过本文,你已完整掌握 Knative Bookstore 前端工程从本地开发到集群部署的全流程,并理解了它如何以 CloudEvent + WebSocket 的方式成为事件驱动架构中的数据入口与实时展示层。
- 文档
- 教程
- 云原生
【免费下载链接】docs
User documentation for Knative components.
相关推荐
Knative Bookstore 前端指南:Next.js 书城应用的本地开发、Docker 容器化与集群部署
Knative Bookstore 前端指南:Next.js 书城应用的本地开发、Docker 容器化与集群部署 本指南围绕 Knative 官方端到端示例应用
文档教程云原生Knative Bookstore 示例应用全解:基于 Knative Eventing 的端到端事件驱动书店系统
Knative Bookstore 示例应用全解:基于 Knative Eventing 的端到端事件驱动书店系统 本篇文章基于 Knative 官方文档仓库中
文档教程云原生Knative Bookstore 示例应用:基于 Knative Eventing 的事件驱动架构端到端实践
Knative Bookstore 示例应用:基于 Knative Eventing 的事件驱动架构端到端实践 导读 code samples/eventing
文档教程云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考