用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Dev-Toolbelt/dev-team-agents --skill sse-streaming命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | sse-streaming |
| description | Server-Sent Events — text/event-stream format, EventSource, reconnection, keep-alive, CORS. |
Server-to-client one-way streaming over plain HTTP. Use for notifications, live feeds, progress updates, dashboards — anything where the server pushes and the client only listens.
| Signal | Action |
|---|---|
| Live notifications, activity feeds, progress bars for long-running jobs, real-time dashboards | Apply this skill |
EventSource, text/event-stream, sse anywhere in the codebase or requirements | Apply this skill |
| Client needs to send data too, not just receive (chat, collaborative editing, low-latency bidirectional) | Do not use SSE — use WebSocket instead |
| Updates are infrequent (minutes apart) and staleness is acceptable | Do not use SSE — plain polling is simpler |
Response Content-Type must be text/event-stream. Messages are field-value lines terminated by \n, and a message ends with a blank line (\n\n).
| Field | Purpose |
|---|---|
event | Names the event type; triggers a matching addEventListener() on the client. Omit to trigger onmessage instead |
data | Payload. Multiple consecutive data: lines are joined with \n — used to stream multi-line payloads |
id | Sets the last-event-id on the client; echoed back as Last-Event-ID on reconnect |
retry | Reconnection delay in milliseconds (integer only; non-integer values are ignored) |
: comment | Any line starting with : is ignored by the client — use for keep-alive pings |
: keep-alive
event: order.updated
id: 482
data: {"orderId": 482, "status": "shipped"}
data: plain message with no event name
data: second line, joined with \n above
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
X-Accel-Buffering: no — otherwise events queue until the proxy buffer fills instead of streaming immediately.Send a : comment line (or a synthetic event: ping) every 15–30 seconds on idle streams. Intermediate proxies and load balancers close connections they consider inactive; a keep-alive line resets that timer without triggering any client-side handler.
id on every message that represents resumable state.Last-Event-ID as a request header. Read it server-side and replay only the events the client missed — never replay the full history by default.id per stream/topic wherever the source events already live (queue offset, DB row id, log sequence) — do not introduce a separate id-tracking store just for this.EventSource cannot set custom request headers, so a bearer token in an Authorization header is not an option for the initial request. Use one of:
withCredentials: true cross-origin) — subject to normal CORS/cookie rules.const source = new EventSource('/api/stream'); // same-origin
const source = new EventSource('/api/stream', { withCredentials: true }); // cross-origin, send cookies
source.onmessage = (e) => {
// fires only for messages with no `event` field
};
source.addEventListener('order.updated', (e) => {
const payload = JSON.parse(e.data);
});
source.onerror = (err) => {
// fires on network drop too — EventSource auto-reconnects unless readyState is CLOSED
};
retry field (default ~3s) and resending Last-Event-ID.source.close() explicitly when the feature no longer needs the stream (component unmount, user navigates away, explicit "stop" action) — closing and recreating on every re-render defeats the reconnection/id-resume machinery.onerror when source.readyState === EventSource.CONNECTING — don't surface a fatal error for a transient drop the browser is already retrying.readyState === EventSource.CLOSED as terminal: the browser gave up (e.g., after a non-retryable HTTP error) and the UI must offer a manual retry, not sit silently disconnected.| Constraint | Detail |
|---|---|
| HTTP/1.1 connection cap | 6 concurrent connections per browser per domain, shared across all tabs. Marked "won't fix" by Chrome and Firefox. Affects any page opening more than one SSE stream, or opening one in multiple tabs. |
| Mitigation | Serve SSE over HTTP/2 — the per-domain cap becomes a negotiated stream count (default 100), not a TCP connection count. |
| Workaround (HTTP/1.1 only) | Spread streams across subdomains if HTTP/2 isn't available — 6 connections apply per domain, not globally. |
| No client → server messages | SSE is receive-only. A feature that later needs the client to push data mid-stream has outgrown SSE — move to WebSocket rather than bolting a second channel on top. |
proxy_buffering off; or the equivalent X-Accel-Buffering: no header) — buffering turns a stream into batched, laggy delivery.