# 问题排查

> Fabric.js 问题排查：loadFromJSON 后自定义属性丢失、UNKNOWN_OBJECT_TYPE、导出时画布被污染、撤销漏记改动。

Source: https://fabricjs-document-engine.jscrate.dev/zh/docs/production/troubleshooting
Last updated: 2026-09-28

这份 Fabric.js 问题排查指南汇总了大家最常遇到的问题，按通常出现的顺序排列。

## 撤销没有记录我的改动

Fabric.js 只在鼠标交互、添加和删除对象、文本编辑时触发事件。你的代码用 `object.set()` 或 `canvas.bringObjectForward()` 做的改动不会触发任何事件。把它们包起来：

```ts
engine.transaction("Recolor", () => shape.set("fill", "teal"));
```

## 撤销后对象引用失效了

撤销和重做会重建改动过的对象，所以它们是 id 不变的新实例。保存 id，再用 `engine.getObjectById(id)` 查找对象。

## 加载后自定义属性丢了

用普通的 `toJSON` 和 `loadFromJSON` 时，Fabric.js 只保存它认识的属性。把类和它的自定义属性注册一下：

```ts
engine.registerObject({ fabricClass: Sticker, properties: ["label"] });
```

## 加载以 UNKNOWN_OBJECT_TYPE 失败

文档里有当前页面没注册的类。通过 `customObjects` 传入，或在加载前调用 `registerObject`。这个类需要一个和保存的 `type` 一致的静态 `type`。在普通 Fabric.js 里，同样的问题会表现为 `klass.fromObject is not a function`。

## 打包结果里有两份 Fabric.js

在一份里注册的类另一份不认识，加载会以 `UNKNOWN_OBJECT_TYPE` 失败。请确认只安装了一份 `fabric`。在 Vite 里使用链接的包时，加上 `resolve: { dedupe: ["fabric"] }`。

## 加载以 MISSING_ASSETS 失败

`error.missingAssets` 列出了每张没加载成功的图片。用 `assets.resolveUrl` 修正地址，用 `assets.replaceMissingImage` 提供替代图片，或者之后调用 `engine.replaceImage(oldUrl, newUrl)`。

## 重新打开后文字显示不一样

创建文字时字体还没加载，所以 Fabric.js 用后备字体测量了它。在 `assets.loadFont` 里加载网络字体，并留意 `FONT_UNAVAILABLE` 警告。

## 导出时画布被污染

有一张来自其他网站的图片没用 CORS 加载，浏览器因此拦截 PNG、JPEG 和 WebP 导出。从返回 `Access-Control-Allow-Origin` 的服务器，用 `crossOrigin: "anonymous"` 加载它。运行 `engine.preflightExport({ format })`，可以在用户点击导出前提示这个问题。

## 只开一个标签页也报 SAVE_CONFLICT

你的适配器没有返回新的修订号。在 `saveDocument` 里返回 `{ revision }`，或者保存 `document.revision`。

## 恢复提示一直不出现

传入 `recovery: { store: createIndexedDbRecovery() }`。只有存在未保存改动时才会写副本；隐私浏览模式可能在关闭窗口时清空存储。

## React：开发环境里有两个引擎

StrictMode 会把 effect 挂载两次。`useDocumentEngine` 会销毁第一个引擎，所以只有一个在运行。始终使用 hook 返回的引擎。

## Vue：加载后画布不渲染

Vue 把 Fabric.js 画布包成了响应式代理。把它放在 `shallowRef` 里，或者传入 `toRaw(canvas)`。详见 [Vue](https://fabricjs-document-engine.jscrate.dev/zh/docs/frameworks/vue)。

## Next.js："window is not defined"

Fabric.js 在服务端运行了。用 `dynamic(() => import("./editor"), { ssr: false })` 加载编辑器。详见 [Next.js](https://fabricjs-document-engine.jscrate.dev/zh/docs/frameworks/next-js)。

如果这份 Fabric.js 问题排查清单没有覆盖你的问题，请带上错误 `code`、Fabric.js 版本和浏览器信息，[提交一个 issue](https://github.com/re-sohail/fabricjs-document-engine/issues)。
