Excalidraw 如何在无互联网环境使用?离线包一键部署
在军工单位的一次封闭式系统设计评审会上,工程师们围坐在会议室里,却无法打开常用的在线白板工具——网络被完全隔离。他们需要快速绘制一个分布式架构图,但所有数据都不能出内网。这时有人从U盘中运行了一个本地服务,浏览器打开后,熟悉的“手绘风”界面出现了:Excalidraw 启动成功,AI插件还能根据语音指令生成拓扑结构。
这不是科幻场景,而是越来越多企业正在落地的真实需求。
当可视化协作成为团队标配时,如何在断网、涉密或边缘环境中保持高效沟通?Excalidraw 凭借其开源、轻量和高度可定制的特性,给出了理想的答案:将整个协作生态打包成可离线运行的独立系统。而这背后的核心,是一套融合前端自治、容器化部署与本地AI推理的技术组合拳。
Excalidraw 本质上是一个纯前端主导的应用。它的绘图逻辑、交互响应、样式渲染全部由浏览器完成,不依赖云端计算资源。默认情况下,画布内容保存在localStorage或IndexedDB中,这意味着哪怕你拔掉网线,依然可以继续编辑并自动保存。这种“客户端即工作站”的设计哲学,让它天生具备离线基因。
当然,原始版本的官网(excalidraw.com)会加载 Google Fonts 和 Sentry 错误监控脚本,这些外部调用必须移除或替换,否则在断网环境下会导致字体缺失或功能卡顿。幸运的是,项目完全开源,我们可以通过构建自定义构建流程来剥离这些依赖。
真正让离线部署变得实用的,是Docker 镜像化封装。想象一下:你在联网机器上执行一条命令拉取官方镜像,然后导出为.tar文件;接着把这个文件拷贝到目标主机,导入并启动容器,几分钟内就能在一个没有外网连接的服务器上跑起完整的 Web 应用。这就是“一键部署”的真实含义。
# 构建离线可用的完整流程 docker pull excalidraw/excalidraw:latest docker save -o excalidraw-offline.tar excalidraw/excalidraw:latest # 在目标机器恢复 docker load -i excalidraw-offline.tar docker run -d -p 8765:80 --name whiteboard excalidraw/excalidraw:latest此时访问http://<内网IP>:8765,即可进入一个完全自主可控的绘图环境。整个容器内存占用仅20–50MB,可在老旧PC、嵌入式设备甚至树莓派上流畅运行。
更进一步,如果团队需要多人协作怎么办?
虽然 Excalidraw 默认以单机模式工作,但它支持通过自建 WebSocket 服务实现房间共享。你可以额外部署一个excalidraw-room服务作为局域网内的通信中枢,所有客户端通过内网IP连接该服务进行实时同步。由于这个后端也可以被打包进 Docker 并与前端共存于同一台物理机,因此整套系统仍然无需公网接入。
但现代生产力工具不止于“能画”,更要“智能辅助”。许多用户已经习惯用自然语言描述来生成图表:“画一个微服务架构,包含用户网关、订单服务和数据库。” 这类 AI 功能通常依赖 OpenAI 或 Claude 的 API,但在离线环境中显然不可行。
解决方案是:把大模型也搬进内网。
借助 Ollama 这样的本地 LLM 运行框架,结合轻量化模型如Phi-3-mini(8GB RAM 可运行)、Llama 3 8B或Mistral 7B,我们可以搭建一个私有的 AI 推理服务。再通过一个适配层(例如 FastAPI 编写的代理网关),模拟 OpenAI 的接口格式,使 Excalidraw 插件无需修改即可调用本地模型。
下面是关键组件的协同方式:
graph LR A[Excalidraw 浏览器] --> B[/api/generate 请求] B --> C{AI Gateway<br>FastAPI 服务} C --> D[Ollama:11434/api/generate] D --> E[(LLM 模型推理)] E --> F[返回 JSON 结构] F --> G[Gateway 转换为 OpenAI 格式] G --> H[Excalidraw 插件解析并绘图]这个代理服务的作用不只是转发请求,还包括:
- 提取模型输出中的 JSON 数据块
- 补全缺失字段以兼容前端解析器
- 添加缓存机制减少重复推理开销
- 支持国产模型微调版本(如通义千问 Qwen 的本地部署版)
来看一段核心代码示例:
# ai_gateway.py from fastapi import FastAPI, Request import httpx import re app = FastAPI() @app.post("/v1/chat/completions") async def handle_completion(request: Request): body = await request.json() prompt = "\n".join([msg["content"] for msg in body["messages"]]) async with httpx.AsyncClient() as client: resp = await client.post( "http://localhost:11434/api/generate", json={"model": body["model"], "prompt": prompt, "stream": False} ) raw_output = resp.json()["response"] # 提取AI返回中的JSON部分(常被包裹在说明文字中) json_match = re.search(r'\{[^}]+\}', raw_output, re.DOTALL) clean_json = json_match.group() if json_match else "{}" return { "choices": [{"message": {"content": clean_json}}] }这段代码看似简单,实则解决了离线AI集成中最常见的“格式错配”问题——很多本地模型不会严格按照 OpenAI Schema 输出结果,而前端插件又极其依赖标准结构。通过中间层做归一化处理,既保留了灵活性,又避免了对 Excalidraw 源码的侵入式修改。
配合docker-compose.yml,我们可以将三个服务统一编排:
version: '3' services: excalidraw: image: excalidraw/excalidraw:latest ports: - "8765:80" ai-gateway: build: ./ai-gateway ports: - "8080:8000" depends_on: - ollama ollama: image: ollama/ollama:latest ports: - "11434:11434" volumes: - ollama-data:/root/.ollama command: serve volumes: ollama-data:一次docker-compose up -d,整套系统就绪。用户只需在 Excalidraw 的 AI 插件设置中,将 API 地址指向http://<内网IP>:8080/v1/chat/completions,即可享受无需联网的智能绘图体验。
这套方案的价值不仅在于技术可行性,更体现在实际业务场景中的适应性。
比如在外场勘测任务中,技术人员携带预装镜像的笔记本到达现场,开机后立即建立热点供团队接入,十几人同时参与方案草图设计,全过程零数据上传。又如金融系统的灾备演练,要求所有操作必须在封闭网络中进行,此时基于 Excalidraw 的本地部署平台就成了唯一合规的协作入口。
更重要的是,它改变了企业对“工具所有权”的认知。过去我们习惯于订阅 SaaS 服务,接受数据托管和功能限制;而现在,通过构建内部镜像仓库(如 Harbor),IT部门可以统一发布经过安全审计的标准化镜像包,确保每个团队使用的都是受控版本,且支持按需扩展权限控制、日志审计、HTTPS 加密等增强功能。
一些高级实践还包括:
- 使用 Nginx 反向代理增加 Basic Auth 登录验证
- 配置定时脚本导出 localStorage 数据至内网 NAS 做备份
- 将 Excalidraw 嵌入企业门户系统,作为子模块集成
- 利用 PWA 特性安装为桌面应用,获得类原生体验
未来已来。随着边缘计算能力的提升和小型化大模型的成熟,“离线智能”正成为高安全等级环境下的新范式。Excalidraw 的案例告诉我们:一个优秀的开源项目,不仅是功能强大,更是架构开放、易于改造、能够融入复杂生产体系。
当你不再依赖云厂商的API,而是把整条技术栈掌握在自己手中时,真正的自主可控才得以实现。而这一切,可以从一个小小的.tar文件开始。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考