Fabric.js Document Engine

搜索文档

查找页面或章节

EN

Fabric.js 留在浏览器里,页面其余部分照常在服务端渲染。

Fabric.js 需要浏览器:它会创建 <canvas> 元素,还会读取 window。在 Fabric.js Next.js 项目里,只在客户端渲染编辑器,页面其余部分照常在服务端渲染。

在客户端渲染编辑器

把编辑器放在单独的文件里并标记 'use client',再用跳过 SSR 的动态导入加载它:

// app/editor/editor-loader.tsx
"use client";
 
import dynamic from "next/dynamic";
 
export const Editor = dynamic(() => import("./editor-client"), {
  ssr: false,
  loading: () => <p>Loading the editor…</p>,
});
// app/editor/page.tsx
import { Editor } from "./editor-loader";
 
export default function EditorPage() {
  return (
    <main>
      <h1>Floor plan</h1>
      <Editor />
    </main>
  );
}

ssr: false 只能在客户端组件里使用,所以加载文件也要写 'use client'。

客户端组件

在 editor-client.tsx 里,用 effect 创建画布并使用 hooks,做法和 React 指南完全一样:

// app/editor/editor-client.tsx
"use client";
 
import { useDocumentEngine } from "fabricjs-document-engine/react";
import { createLocalStorage } from "fabricjs-document-engine/storage";
 
import { useFabricCanvas } from "./use-fabric-canvas";
 
const storage = createLocalStorage({ prefix: "plans:" });
 
export default function EditorClient() {
  const { elementRef, canvas } = useFabricCanvas(1200, 800);
  const engine = useDocumentEngine(canvas, { storage, autosave: true });
 
  return <canvas ref={elementRef} aria-label="Floor plan editor" />;
}

fabricjs-document-engine/react 入口已经标记了 'use client',所以导入这些 hooks 不会影响服务端组件。

在服务端

文档相关的辅助函数在 Node 里无需画布也能运行。在路由处理函数里用它们,先检查上传的文档再存储:

// app/api/documents/[id]/route.ts
import { secureDocument, validateDocument } from "fabricjs-document-engine";
 
export async function PUT(request: Request) {
  const document = secureDocument(await request.json());
  if (validateDocument(document).length > 0) {
    return new Response("Invalid document", { status: 422 });
  }
  // Store the document, checking the revision in the same query.
  return Response.json({ revision: 1 });
}

Fabric.js Next.js 常见错误

  • "window is not defined":Fabric.js 在 SSR 时运行了。用 ssr: false 加载编辑器。
  • "useState only works in client components":在标记了 'use client' 的文件里,从 fabricjs-document-engine/react 导入 hooks。

更多解决办法见问题排查。