iframe 快速入门
这是无需先构建后端即可试用开发者 API 的最快方法。
在 iframe 模式下,您的应用通过 postMessage 与 Chastify 父应用通信,而 Chastify 代表您调用服务器 API。
Chastify 会将什么传递给你的 iframe
打开时,Chastify 将 JSON 有效负载放入 location.hash 中。
重要字段:
bridge.nonce:桥接消息的请求签名值。bridge.parentOrigin:postMessage所需的目标来源。sessionId:此锁的稳定扩展会话 ID。lockId:活动锁 ID。ui:来自父页面的主题值。- 可选:
homeActionSlug、homeAction、intent、regularActionsSummary、mainToken。
Bridge Library 快速入门(推荐)
使用 apps/extension/src/lib/ChastifyBridge.ts 中的辅助函数:
parseHashPayload()ChastifyBridgeClientstartAutoResizeToParent(...)themeVars(...)
极简 React Bootstrap
import { useEffect, useMemo, useState } from "react";
import {
parseHashPayload,
ChastifyBridgeClient,
startAutoResizeToParent,
themeVars,
} from "../lib/ChastifyBridge";
const payload = parseHashPayload();
if (!payload?.bridge?.nonce || !payload?.bridge?.parentOrigin) {
throw new Error("Missing bridge payload in iframe hash");
}
export function App() {
const [client, setClient] = useState<ChastifyBridgeClient | null>(null);
const [session, setSession] = useState<any>(null);
const [stateDoc, setStateDoc] = useState<any>(null);
const vars = useMemo(() => themeVars(payload.ui ?? null), []);
useEffect(() => {
const c = new ChastifyBridgeClient({
nonce: payload.bridge!.nonce,
targetOrigin: payload.bridge!.parentOrigin,
});
setClient(c);
return () => c.destroy();
}, []);
useEffect(() => {
if (!client) return;
(async () => {
const s = await client.request("session.get", {});
setSession(s);
const st = await client.request("state.get", {});
setStateDoc(st);
})().catch(console.error);
}, [client]);
useEffect(() => {
return startAutoResizeToParent({
nonce: payload.bridge!.nonce,
targetOrigin: payload.bridge!.parentOrigin,
extraPx: 12,
});
}, []);
return (
<div style={{ background: vars.pageBg, color: vars.text, minHeight: "100%" }}>
<h2>Extension Quickstart</h2>
<pre>{JSON.stringify(session, null, 2)}</pre>
<pre>{JSON.stringify(stateDoc, null, 2)}</pre>
</div>
);
}
原始 postMessage 示例(无辅助类)
如果您不使用 ChastifyBridgeClient,请手动发送完整的请求信封:
const req = {
type: "chastify:ext:req",
v: 1,
id: crypto.randomUUID(),
nonce,
action: "session.get",
payload: {},
};
window.parent.postMessage(req, parentOrigin);
留意是否有匹配的回应:
window.addEventListener("message", (event) => {
if (event.origin !== parentOrigin) return;
const msg = event.data;
if (!msg || msg.type !== "chastify:ext:resp" || msg.v !== 1) return;
if (msg.id !== req.id) return;
if (msg.ok) console.log("Bridge success:", msg.data);
else console.error("Bridge error:", msg.error);
});
首先应该运行的测试流程
session.getstate.getmetadata.getregularActions.get
这确认了桥接身份验证、安全读取以及请求/响应处理。状态写入必须由您的后端使用开发者 API 凭据执行。
从 iframe 上传文件
如果您的扩展程序需要图像或生成的媒体,请使用桥接文件助手。Chastify 会将文件上传到托管的 R2 存储,返回一个稳定的文件 ID,并提供一个用于渲染的短期签名 URL。
const capabilities = await client.filesCapabilities();
if (capabilities.enabled) {
const uploaded = await client.filesUpload({
file,
filename: file.name,
purpose: "puzzle-image",
});
// Send uploaded.file.id to your backend if it should be stored in session state.
const refreshed = await client.filesGet(uploaded.file.id);
image.src = refreshed.file.signedUrl;
}
存储 uploaded.file.id,而不是已签名的 URL。已签名的 URL 会过期,当 iframe 再次加载时,应使用 files.get / client.filesGet(...) 刷新。
主题支持(ui + themeVars)
Chastify 在 iframe 哈希中传递 ui 对象。
themeVars(ui) 将其转换为可用的设计令牌:
pageBgtextpanelbordermutedinputBg
使用这些值作为扩展程序的基本样式,以便您的 iframe 与宿主主题相匹配。
实时主题更新
当您的 iframe 打开时,父级可以发送 chastify:ext:ui 事件。
如果想要实时主题同步,请监听该事件并更新本地主题状态。
有关浅色/深色主题处理的详细说明、对比度示例和 Tailwind 模式,请参阅Iframe 主题。
自动调整大小支持
使用 startAutoResizeToParent(...),以便父元素可以根据您的内容调整 iframe 的大小。
重要性:
- 防止 iframe 内出现滚动陷阱。
- 保持设置模态框和扩展页面大小正确。
- 适用于可展开/折叠的动态部分。
常见错误
targetOrigin错误(必须与bridge.parentOrigin匹配)。nonce缺失或过期。- 卸载
ChastifyBridgeClient时不调用destroy()。 - 未先检查
session.get功能,就发送不支持的操作。
参考文件
apps/extension/src/lib/ChastifyBridge.tsapps/extension/src/pages/MainPage.tsxapps/extension/src/pages/SetupPage.tsx