Claude Artifact 渲染成空白面板

Artifact 打开后一片白。最快修法:打开 iframe console,把第一条红字原样发回 Claude。覆盖 sandbox 存储报错、cdnjs 白名单、以及发布版 artifact 的 origin 故障。

让 Claude 写一个 React 组件或者一页 HTML,右侧 artifact 面板打开了,里面却是纯白。没有报错、没有 spinner。Preview 标签空白,但 Code 标签里源码是齐的。这种情况几乎都是 sandbox iframe 内部抛了 JS 异常但 Claude 主界面没接住,或者是被 revoke 的旧 blob frame 残留。

最快的修法(约九成情况有效):先硬刷新一次(Cmd-Shift-R / Ctrl-Shift-F5)。还是空白,就打开 DevTools,把 Console 切到 artifact 那个 iframe,第一条红字一字不差复制下来,发回给 Claude:「预览空白,iframe console 报错如下,请修复并重新出一份。」只要看到真实报错,Claude 基本一次就能改对。

先判断属于哪一类

动手改之前,先把所属的类别钉死。

你看到的现象最可能的原因跳到
重新生成 / 编辑后变空白,刷新就好旧 blob frame 被 revokeStep 1
iframe console 里有红字报错未捕获的 JS 异常(少 import、typo)Step 2-3
报错提到 localStoragesessionStorageAccess is deniedsandbox 里调用了浏览器存储Step 4
Network 里某个 script 行是 404 / text/html用了不在白名单的 CDNStep 5
React 挂上去了但页面视觉上是空的Tailwind/CSS 没加载,或命中了 return nullStep 6-7
只有分享出去的 claude.ai/public/artifacts/... 链接空白发布版 artifact 的 origin 故障Step 8

常见原因

按命中率从高到低。

1. Sandbox iframe 内未捕获的 JS 异常

Artifact 预览跑在一个独立 JS 上下文的 sandbox <iframe> 里。顶层一个 ReferenceErrorSyntaxErrorTypeError 会让 React 树直接挂不上去,但外层 Claude UI 看不到这个错。

怎么判断:打开 DevTools,在空白面板上右键选「检查 frame」,或者在 Console 顶部的上下文下拉里挑那个 iframe。里面那条红字就是元凶。

2. Sandbox 里调用了浏览器存储

这是截至 2026 年 6 月最容易被漏掉的一类。Claude 的预览 iframe 是带 sandbox 且不带 allow-same-origin 的,所以任何对 localStoragesessionStorageindexedDB 的调用都会立刻抛异常、中断渲染。Claude 经常为了「记住设置」这类功能写 localStorage.getItem(...),没意识到 sandbox 根本不让用。

怎么判断:iframe console 里出现这条原文:

Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.

3. import 了不在 Claude 白名单里的 CDN

Claude 的 artifact sandbox 只允许从 https://cdnjs.cloudflare.com 加载外部脚本。React、Tailwind、Recharts、shadcn/ui、lucide-react 都是预装好的,直接 import 即可,不用挂 CDN 标签。如果 Claude 为别的包写了 esm.shunpkg.comcdn.jsdelivr.net 的 URL,请求会被拦或 404,import 也就不执行。

怎么判断:DevTools Network 切到 artifact iframe,看 JS 资源行里有没有 404 / 503 / Content-Type: text/html;或者 console 里出现 Refused to load the script ... because it violates the Content Security Policy,host 不是 cdnjs.cloudflare.com

4. 浏览器缓存里还压着上一份空 frame

你重新生成了 artifact,但 iframe 还指着上一个 blob URL,那个 URL 此刻已经被 revoke 了。后续渲染拉到的是 about:blank

怎么判断:硬刷新一下(Cmd-Shift-R / Ctrl-Shift-F5)。刷完出来了,就是缓存 / blob revoke 问题。

5. 用了 Tailwind class 但 Tailwind 没生效

大多数 React artifact 自带 Tailwind。但在纯 HTML artifact 里,Claude 有时会写 className="bg-blue-500 p-4" 而文档里压根没 Tailwind。布局塌成 0 高度容器,看起来就是空白——其实树已经挂上去了。

怎么判断:DevTools → Elements 看 iframe,<div> 在但 width: 0height: 0;或者文档 <head> 里根本没引 Tailwind。

6. 组件 default export 出去的函数命中了 return null

Claude 常见的小坑:默认导出的组件里有 if (!data) return null; 但没给初始数据,预览正好命中 null 分支。

怎么判断:Code 标签搜 return null。有的话让 Claude 加 loading 态或者初始 state。

7. 发布版 artifact 的 origin 故障(分享的 /public/artifacts/ 链接)

这跟编辑器内的预览是两回事:大约 2026 年 4 月 1 日起出现的一个回归,让部分由 claudeusercontent.com 托管的已发布 artifact 在通过 claude.ai/public/artifacts/... 分享链接打开时渲染成空白,原因是 postMessage 的 target origin 对不上。你自己对话里的编辑器预览不受影响。

怎么判断:发布页的 console 里出现下面之一的原文:

Failed to execute 'postMessage' on 'Window': Invalid target origin 'app://localhost' in a call to 'postMessage'.
The target origin provided ('https://www.claudeusercontent.com') does not match the recipient window's origin ('https://claude.ai').

开始前

  • 看看是只这次对话的 artifact 空白,还是每次都空——只这次的话问题在 artifact 代码本身。
  • 用无痕窗口和另一个浏览器再试一遍,一次性隔离扩展、广告拦截(uBlock、Privacy Badger)和缓存的影响。
  • 当前对话别关,等下要用这个 artifact 和那条 Claude 回复来要求修复。

需要收集的信息

  • iframe console 里的报错原文(红字一字不差贴出来,别概括)。
  • Code 标签也空白,还是只有 Preview 空白。
  • 浏览器 + 版本、OS、有没有装拦截类扩展(uBlock、Brave Shields、MDM 配置,或者会注入 CSP 的公司代理/VPN)。
  • Artifact 类型:React、HTML、SVG、Mermaid,还是纯代码。
  • 同一对话里别的 artifact 渲染是否正常。

一步一步修复

Step 1:先硬刷新一次

Mac 上 Cmd-Shift-R,Windows 上 Ctrl-Shift-F5。相当一部分空白面板就是被 revoke 的 blob 残留,刷一下就好。出来了就完事。

Step 2:打开 iframe 的 console

DevTools 里点 Console 顶部的上下文下拉(默认写「top」),切到路径像 claude.siteclaudeusercontent.com 的那个 iframe,重跑 artifact,第一条红字就是真正的失败原因。

Uncaught ReferenceError: useEffect is not defined
  at Component (index.js:14)

Step 3:把报错原话发回 Claude

iframe 里那行错误原样复制粘贴回去:

artifact 预览空白。iframe console 里是:
Uncaught ReferenceError: useEffect is not defined at index.js:14

请修一下、重新出一份 artifact。

只要给到真实报错,Claude 基本一次就能改对。

Step 4:报错提到存储,就把存储调用去掉

如果 console 出现上面那条 localStorage / sessionStorageAccess is denied SecurityError,说明这个 sandbox 里 artifact 根本用不了浏览器存储。回复:

这个 artifact 用了 localStorage,而 artifact sandbox 禁用了它。
请把所有需要持久化的状态改成 React state(useState/useReducer)
或者内存变量。

sessionStorageindexedDB 同理。预览里没有开关能开启它们——改成内存态是唯一的修法。

Step 5:对照 cdnjs 白名单检查 import

console 干净但面板仍然空白,去 iframe 自己的 Network 标签,filter js。任何一行 404,或者 console 里 Refused to load the script ... because it violates the Content Security Policy 这种行,就是凶手。sandbox 只允许 cdnjs.cloudflare.com 的外部脚本。

你看到的原因修法
esm.sh/...unpkg.com/... 被拦或 404host 不在白名单让 Claude 用预装库,或换 cdnjs.cloudflare.com 的 URL
cdn.jsdelivr.net/... 被 CSP 拒绝host 不在白名单cdnjs.cloudflare.com
cdn.tailwindcss.com 不生效React artifact 里本就不需要用内置 Tailwind;HTML 的话从 cdnjs 加载 Tailwind

prompt 模板:

这个 import 被 artifact sandbox 拦了,它只允许 cdnjs.cloudflare.com。
有预装库就用预装的(React、Tailwind、Recharts、shadcn/ui、lucide-react),
没有的话从 cdnjs.cloudflare.com 加载。

Step 6:确认 Tailwind / CSS 真的生效

如果是纯 HTML artifact,树挂上去了但页面视觉上空,去看 iframe 源码确认 Tailwind 在。HTML artifact 就回复 Claude:

请从 cdnjs.cloudflare.com 加载 Tailwind(artifact sandbox 会拦其他 CDN),
让 utility class 真正生效,或者直接内联 style。

React artifact 自带 Tailwind,所以 React 预览没样式时,应该去找 return null 分支,而不是去加 Tailwind。

Step 7:让 Claude 加一个 error boundary

针对 React artifact,要求:

把根组件包一层 React error boundary,
把错误消息直接渲染出来,
这样以后空白渲染就变成可见的报错了。

下次再空白就能自己暴露原因,不用 DevTools。

Step 8:分享 / 发布链接空白,先别怀疑自己的代码

如果只在你分享的 claude.ai/public/artifacts/... 链接上空白,且 console 是上面那条 app://localhost / claudeusercontent.compostMessage 报错,说明你的 artifact 代码没问题——这是服务端发布版 artifact 的回归。回到自己对话里看编辑器预览,确认能正常渲染,然后看一眼 status.anthropic.com,并关注跟踪 issue(anthropics/claude-code#42064)。重新发布一次有时会生成一个能用的新链接。

Step 9:实在不行就让它从头重写

artifact 已经被编辑过 5 次以上、改得很乱,就让 Claude「一次性从头重写这个 artifact、不在原基础上改」。干净重生比堆 diff 靠谱。

怎么验证修好了

  • 在新标签页重新打开这个对话,不开 DevTools 也能看到 artifact 正常出来。
  • 换一个浏览器打开(Chrome 上看就换 Safari),渲染结果应该一致。
  • 在 Code 和 Preview 标签之间来回切,面板不应该又变白。
  • 如果是交互型 artifact,点一下按钮或填一下输入框,iframe console 应保持干净——没有新红字。

长期预防

  • 稍微复杂点的 artifact,开头就让 Claude「根组件包 error boundary,挂载时打一条 log」。
  • artifact 里别用 localStorage/sessionStorage/indexedDB——sandbox 会拦,用内存态或 React state。
  • 尽量只用预装库(React、Tailwind、Recharts、shadcn/ui、lucide-react);别的依赖一律从 cdnjs.cloudflare.com 加载。
  • 在 artifact 上反复迭代时让 DevTools 一直开着,iframe 报错当场抓,别拖到三轮之后。
  • artifact 长起来就拆:一份做数据层、一份做 UI,越小越不容易空白。
  • 收藏 status.anthropic.com,开搞之前先看一眼,有时是 artifact 服务自己降级了。

容易踩的坑

  • 看了外层页面的 console,没去看 iframe 的——什么都看不到。
  • 默认认为「Preview 空白 = Claude 坏了」,几乎都是少了一个 import 或调用了存储。
  • 让 Claude 加 localStorage 来做持久化;它在预览里根本跑不了,每次都会把面板搞白。
  • 为修一个 typo 在原 artifact 上编辑 10 次,不如让它整篇重写一次。
  • 一个个禁用扩展去排查,其实开个无痕窗口 5 秒就能判断。

常见问答

  • 为什么 Claude 自己界面里看不到 iframe 报错? Artifact sandbox 是有意隔离的,外层界面按设计就读不到 iframe 内部,所以致命运行时错误看上去就是一片白。
  • 为什么 artifact 在编辑器里好好的,一分享链接就空白? 那是发布版 artifact 的 origin 故障(Step 8),是 claudeusercontent.com 上服务端的 postMessage 不匹配,不是你代码的问题。
  • artifact 到底能不能用 localStorage? 不能。localStoragesessionStorageindexedDB 在 sandbox 里都会抛 Access is denied。用 React state 或内存变量;真要持久化就自己托管这个应用。
  • artifact 能 import 哪些库? React、Tailwind、Recharts、shadcn/ui、lucide-react 是预装的。别的都得从 cdnjs.cloudflare.com 加载——esm.shunpkgjsdelivr 不在白名单里。
  • 空白面板会不会是账号被限流? 不会。限流会显示 rate-limit 横幅,不会表现成空 artifact。
  • 能把坏掉的 artifact 下回本地跑吗? 可以,Code 标签是好的。把源码存下来、装依赖、用 vite 跑就行——本地环境没有 sandbox 限制,存储和任意 CDN 都能用。

相关

标签: #Claude #排查 #artifacts