news 2026/9/5 19:53:08

Excalidraw 开源虚拟白板的架构剖析:npm 包集成、核心特性与本地开发全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Excalidraw 开源虚拟白板的架构剖析:npm 包集成、核心特性与本地开发全流程

Excalidraw 开源虚拟白板的架构剖析:npm 包集成、核心特性与本地开发全流程

【免费下载链接】excalidrawVirtual whiteboard for sketching hand-drawn like diagrams项目地址: https://gitcode.com/GitHub_Trending/ex/excalidraw

Excalidraw 是一个开源的虚拟手绘风格白板,支持实时协作与端到端加密。本文以仓库根目录 README.md 为主线,完整覆盖其特性清单、excalidraw.com 应用架构、@excalidraw/excalidrawnpm 包的集成方法,并结合 monorepo 源码结构、packages/excalidraw包配置与开发文档,讲透从安装到本地运行的每一步,帮助你既能快速把 Excalidraw 嵌入自己的 React 应用,也能在本地完整跑起开发、测试与容器化部署。

项目定位与仓库总体结构

按 README.md 的定义,Excalidraw 是一个开源、协作、端到端加密的虚拟手绘风格白板,可用于绘制手绘风格的图表、线框图或任何你喜欢的东西。它有两个交付形态:

  1. npm 包@excalidraw/excalidraw):以 React 组件形式嵌入你自己的应用,核心源码位于 packages/excalidraw;
  2. excalidraw.com 在线应用:README 将其定位为“用 Excalidraw 可以构建什么”的最小化展示(minimal showcase),源码就在本仓库的 excalidraw-app 目录中。

从 根目录 package.json 看,这是一个基于 Yarn workspaces 的 monorepo(excalidraw-monorepo),工作区声明为excalidraw-apppackages/*examples/*,并要求 Node.js>=18.0.0packages/下的子包划分揭示了清晰的模块边界:

包目录职责
packages/excalidraw对外发布的 React 组件包@excalidraw/excalidraw(当前版本 0.18.0),包含编辑器、渲染器、组件、动作系统、i18n 等
packages/element元素模型与几何逻辑(对齐、分组、帧、箭头绑定、碰撞检测、文本换行等),测试覆盖binding.test.tsxelbowArrow.test.tsx等场景
packages/common跨包共享的基础工具:bounds、colors、keys、promise-pool、random、url 等
packages/math数学运算子包
packages/fractional-indexing分数索引(用于协作场景下的有序列表)
packages/laser-pointer激光笔动画轨迹子包
packages/utils通用工具

excalidraw-app的 package.json 则依赖firebasesocket.io-client@sentry/browser等,印证了在线应用的协作与监控能力;仓库根部的 firebase-project 目录存放了 Firestore 规则、索引等协作后端配置。

npm 包(编辑器)支持的核心特性

README.md 的 Features 一节列出了 Excalidraw 编辑器(npm 包)支持的能力,这里完整继承:

  • 免费且开源(MIT 协议);
  • 基于 Canvas 的无限画布白板;
  • 手绘风格渲染;
  • 暗色模式;
  • 可定制;
  • 图片支持;
  • 图形库(shape libraries)支持;
  • 本地化(i18n)支持;
  • 导出为 PNG、SVG 与剪贴板;
  • 开放格式——将绘图导出为.excalidrawJSON 文件;
  • 丰富的工具集:矩形、圆形、菱形、箭头、直线、自由绘制、橡皮擦等;
  • 箭头绑定与带标签箭头(labeled arrows);
  • 撤销 / 重做;
  • 缩放与平移支持。

这些特性在源码中都有对应实现可以印证:

  • 手绘风格来自依赖roughjs(见 packages/excalidraw/package.json 的 dependencies),它负责生成“抖动”的手绘线条;
  • 工具与动作系统位于 packages/excalidraw/actions,如 actionAlign.tsx、actionExport.tsx、actionGroup.tsx、actionZindex.tsx,配合 shortcuts.ts 定义快捷键;
  • 渲染管线在 packages/excalidraw/renderer,包含动态场景(interactiveScene)、静态导出(staticScene、staticSvgScene,对应 PNG/SVG 导出);
  • i18n 由 packages/excalidraw/i18n.ts 驱动,packages/excalidraw/locales 目录下收录了zh-CNzh-TWja-JPde-DEfr-FR等 60 余种语言的翻译文件;
  • 开放格式.excalidrawJSON 的读取/保存逻辑在 packages/excalidraw/data(json、encode、encryption、restore 等模块)。

excalidraw.com 应用:协作、加密与本地优先

README 指出,excalidraw.com 是 Excalidraw 能力的最小化展示,其源码包含在仓库中(excalidraw-app),并且具备以下特性:

  • PWA 支持(可离线工作):从 excalidraw-app/index.tsx 可以看到registerSW()(Service Worker 注册)调用,根 package.json 的 devDependencies 中也有vite-plugin-pwapwacompat
  • 实时协作:excalidraw-app/collab 目录包含协作 UI(Collab.tsx、CollabError.tsx、Portal.tsx),依赖socket.io-client与 Firebase;
  • 端到端加密:客户端加密工具在 packages/excalidraw/data/encryption.ts;
  • 本地优先(自动保存到浏览器):excalidraw-app/data 中的 LocalData、localStorage、tabSync 等模块负责浏览器端自动保存与多标签页同步;
  • 可分享链接(导出只读链接):excalidraw-app/share 目录提供分享对话框与 QR 码能力。

README 还明确说明:这些应用级特性未来会作为“即插即用插件(drop-in plugins)”提供给 npm 包。

快速开始:把 Excalidraw 集成进你的 React 应用

README 的 Quick start 指出:以下说明针对将 npm 包集成进你自己的应用的场景;若要在本地运行仓库进行开发,则应参考开发指南(见下文“本地开发”一节)。安装命令:

npm install react react-dom @excalidraw/excalidraw # 或 yarn add react react-dom @excalidraw/excalidraw

从 packages/excalidraw/README.md 与 packages/excalidraw/package.json 可以得到几个关键事实:

  • React 版本约束(peerDependencies)reactreact-dom需为^17.0.2 || ^18.2.0 || ^19.0.0之一;
  • 包版本:当前发布版本为0.18.0(如需试用未发布变更可用@excalidraw/excalidraw@next);
  • exports 映射:包根入口按条件导出development/production/default指向dist/dev/index.jsdist/prod/index.js,样式单独从@excalidraw/excalidraw/index.css引入(同样区分 dev/prod 两份 CSS)。

最小可运行配置的两个易错点

子包 README 特别强调“最小工作配置有两个容易漏掉的要求”:

  1. 必须引入包的 CSS
import "@excalidraw/excalidraw/index.css";
  1. 必须在非零高度的容器中渲染(Excalidraw 会填满父容器的 100% 宽高,父容器没有高度时画布不可见):
import { Excalidraw } from "@excalidraw/excalidraw"; import "@excalidraw/excalidraw/index.css"; export default function App() { return ( <div style={{ height: "100vh" }}> <Excalidraw /> </div> ); }

Next.js 等 SSR 框架下的客户端渲染

Excalidraw 必须在客户端渲染。在 Next.js 这类 SSR 框架中,应使用 client component 并以禁用 SSR 的方式动态加载:

// app/components/ExcalidrawClient.tsx "use client"; import { Excalidraw } from "@excalidraw/excalidraw"; import "@excalidraw/excalidraw/index.css"; export default function ExcalidrawClient() { return ( <div style={{ height: "100vh" }}> <Excalidraw /> </div> ); }
// app/page.tsx import dynamic from "next/dynamic"; const ExcalidrawClient = dynamic( () => import("./components/ExcalidrawClient"), { ssr: false }, ); export default function Page() { return <ExcalidrawClient />; }

仓库自带了两套完整示例可作参考:examples/with-nextjs(其中 excalidrawWrapper.tsx 展示了"use client"+ 组件包装的写法)与 examples/with-script-in-browser(Vite 驱动的浏览器脚本集成示例,入口见 index.html 与 ExampleApp.tsx)。

字体自托管与 0.18.x 迁移注意

  • 字体自托管:默认情况下 Excalidraw 会从 CDN 下载所需字体;自托管时需将node_modules/@excalidraw/excalidraw/dist/prod/fonts的内容拷贝到应用的静态资源路径(如public/),并设置window.EXCALIDRAW_ASSET_PATH指向同一路径;
  • 0.18.x 类型导入路径变更:0.18.x 移除了旧的types/前缀深层导入路径,子包 README 给出了完整对照表:
旧路径新路径
@excalidraw/excalidraw/types/data/transform.js@excalidraw/excalidraw/element/transform
@excalidraw/excalidraw/types/data/types.js@excalidraw/excalidraw/data/types
@excalidraw/excalidraw/types/element/types.js@excalidraw/excalidraw/element/types
@excalidraw/excalidraw/types/utility-types.js@excalidraw/excalidraw/common/utility-types
@excalidraw/excalidraw/types/types.js@excalidraw/excalidraw/types

这些深层子路径仅用于import type;运行时导入应从包根入口引入,样式则从@excalidraw/excalidraw/index.css引入。这与 packages/excalidraw/package.json 中exports字段对./common/*./element/*./math/*./utils/*的类型映射一致。

本地开发:从零跑起 Excalidraw 仓库

README 提示本地开发请参阅开发指南,对应仓库内的 dev-docs/docs/introduction/development.mdx。该指南给出的完整流程如下:

环境要求

  • Node.js
  • Yarn(v1 或 v2.4.2+;仓库packageManager字段声明为yarn@1.22.22
  • Git

克隆并安装

git clone https://github.com/excalidraw/excalidraw.git yarn

启动开发服务器

yarn start

启动后即可访问http://localhost:3000开始编码。对照根 package.json,start实际转发到excalidraw-app工作区执行yarn && vite(见 excalidraw-app/package.json 的 scripts),即通过 Vite 驱动开发服务。

协作功能的前置条件

指南指出:要本地体验实时协作,需要自行部署协作服务器(collab server,即独立的 excalidraw-room 项目)。仓库内 firebase-project 提供了 Firestore 规则与索引配置,属于该协作体系的组成部分。

常用命令一览

以下命令均收录于开发指南,并与根 package.json 的 scripts 一一对应:

yarn # 安装依赖 yarn start # 运行项目(Vite 开发服务器) yarn fix # 用 Prettier + ESLint 格式化全部文件 yarn test # 运行测试(vitest) yarn test:update # 更新测试快照 yarn test:code # Prettier/ESLint 格式检查

此外,test:all会依次执行test:typecheck(tsc 类型检查)、test:code(ESLint,--max-warnings=0)、test:other(Prettier 检查)与test:app(vitest 用例)。测试框架为 vitest,配置见 vitest.config.mts 与 setupTests.ts。

Docker Compose 方式

如果不想配置 Node.js 环境,指南提供了 Docker Compose 方案(仓库根目录含 docker-compose.yml):

docker-compose up --build -d

自托管:Docker 镜像构建与运行

开发指南的 Self-hosting 一节说明,官方发布了 Excalidraw 客户端的 Docker 镜像,可用于在自有域名下、Kubernetes、AWS ECS 等环境中自托管。构建与运行命令:

docker build -t excalidraw/excalidraw . docker run --rm -dit --name excalidraw -p 5000:80 excalidraw/excalidraw:latest

镜像内容不含分析与追踪类库。指南同时提醒:目前自托管实例不支持分享与协作功能(需要协作服务端支持),团队正在朝完整的自托管方案努力。

这一流程与仓库根部的 Dockerfile 完全吻合,其实现细节值得注意:

  • 构建阶段基于node:24多平台镜像,使用yarn --frozen-lockfile安装依赖(并注释说明不能忽略可选依赖,否则会出现Cannot find module @rollup/rollup-linux-x64-gnu错误);
  • 构建命令为yarn build:app:docker,对应 excalidraw-app/package.json 中的cross-env VITE_APP_DISABLE_SENTRY=true vite build——即在 Docker 构建时禁用 Sentry;
  • 运行阶段为nginx:stable-alpine-slim,将excalidraw-app/build产物拷入/usr/share/nginx/html,并带wget健康检查。

测试、构建与发布脚本

根 package.json 的 scripts 揭示了完整的工程化流水线:

  • 子包构建build:packages按依赖顺序依次构建 common → fractional-indexing → laser-pointer → math → element → excalidraw(每个子包执行各自的build:esm),最终产物只发布dist/*(见 packages/excalidraw/package.json 的files字段);
  • 应用构建build:appexcalidraw-app中执行cross-env VITE_APP_GIT_SHA=... VITE_APP_ENABLE_TRACKING=true vite buildwindow.__EXCALIDRAW_SHA__即由该环境变量注入(见 excalidraw-app/index.tsx);
  • 发布release/release:next/release:latest脚本调用 scripts/release.js;
  • 其他工具locales-coverage(统计翻译覆盖度)、buildWasm.js(构建 harfbuzz/woff2 子集化 wasm,产物位于 scripts/wasm)、字体子集化相关脚本等。

集成生态与参与贡献

README 列出的集成包括 VS Code 扩展与 npm 包两条外部入口;仓库内examples/下则提供了可直接运行的参考实现(with-nextjs 与 with-script-in-browser)。README 还列出了 Google Cloud、Meta、CodeSandbox、Obsidian Excalidraw、Replit、Slite、Notion、HackerRank 等在集成 Excalidraw。

贡献方面,README 给出三条路径:

  • 缺少功能或发现 Bug:通过仓库 issue 报告;
  • 参与贡献:参考 dev-docs/docs/introduction/contributing.mdx(仓库根部的 CONTRIBUTING.md 也指向该文档);
  • 参与翻译:参见贡献指南中的 translating 章节,翻译文件位于 packages/excalidraw/locales。

小结

回到 README.md 的主线:Excalidraw 以@excalidraw/excalidrawReact 组件包为能力核心,以 excalidraw-app 作为协作、加密、PWA、本地优先等特性的在线展示,两者共享同一 monorepo 中的packages/*子包实现。集成侧的关键要点是“CSS 引入 + 非零高度容器 + SSR 场景禁用 SSR”,开发侧的关键路径是“yarn 安装 → yarn start 本地开发 → vitest 测试 → Docker 构建自托管镜像”。文中所有命令、路径与配置均可在当前仓库中直接查证,适合作为集成或二次开发的起点。

【免费下载链接】excalidrawVirtual whiteboard for sketching hand-drawn like diagrams项目地址: https://gitcode.com/GitHub_Trending/ex/excalidraw

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 19:49:51

技术写作切忌凭空编造:4类可落地的技术选题方向指南

很抱歉&#xff0c;我无法根据这个项目标题生成一篇有真实技术价值和技术深度的CSDN技术博客。原因是&#xff1a;20op24gp24hp24bp 1压抑这组输入既不是一个可辨认的技术项目名称&#xff0c;也不包含任何可理解的技术上下文、功能描述、关键词或应用场景。如果强行围绕它“扩…

作者头像 李华
网站建设 2026/9/5 19:48:42

技术文档生成失败的原因与信息补充策略

标题 20op24gp24hp24bp 1压抑 无法识别为可具体展开的技术项目、开源模型、开发工具或部署方案&#xff0c;也没有提供项目正文、关键词、摘要描述或网络背景材料。为避免编造功能、参数和操作步骤&#xff0c;这篇 CSDN 技术博文本次无法生成。 如果你希望我继续&#xff0…

作者头像 李华
网站建设 2026/9/5 19:47:05

Emlog6.0资源模板源码深度解析与部署实战

简介&#xff1a;这是一套基于Emlog 6.0开发的完整资源类网站模板源码&#xff0c;面向个人站长、小型内容平台运营者及PHP入门开发者&#xff0c;解决从零建站、内容自动聚合与广告变现一体化落地的刚需。资源包共49个文件&#xff0c;涵盖13个核心PHP逻辑文件&#xff08;如i…

作者头像 李华
网站建设 2026/9/5 19:45:11

SG90连续旋转舵机:开环速度控制,不是角度舵机

如果你手里的元件 是 SG90 的“360 度连续旋转”版本&#xff0c;那么你多半会经历一个很拧巴的阶段&#xff1a;把原来驱动普通舵机的那套writeMicroseconds代码原样搬过来&#xff0c;发现舵机要么一直转&#xff0c;要么转起来没有停的意思&#xff0c;甚至你给它传了一个“…

作者头像 李华
网站建设 2026/9/5 19:42:07

免费开源中文字体霞鹜文楷完整指南:2万余字库与安装方法

免费开源中文字体霞鹜文楷完整指南&#xff1a;2万余字库与安装方法 【免费下载链接】LxgwWenKai An open-source Chinese font derived from Fontworks Klee One. 一款开源中文字体&#xff0c;基于 FONTWORKS 出品字体 Klee One 衍生。 项目地址: https://gitcode.com/Git…

作者头像 李华
网站建设 2026/9/5 19:35:15

SpringBoot+Vue足球俱乐部管理系统:全栈开发与工程实践详解

简介&#xff1a;这是一套面向计算机及相关专业本科生的高分毕业设计实战项目源码&#xff0c;聚焦足球俱乐部全流程数字化管理需求&#xff0c;适用于毕设开发、课程设计与期末大作业等实践场景。系统采用前后端分离架构&#xff0c;前端基于Vue.js构建响应式管理界面&#xf…

作者头像 李华