docx-editor - React/Vue 都能用的开源 .docx 在线编辑器,纯前端实现无需后端

一个同时给到 React 和 Vue 3 的所见即所得文档编辑器,Apache 2.0 开源,无后端依赖。

前言

上周接了个临时需求:要在 Web 后台里加一个“在线编辑 .docx”的功能,用户上传合同模板,在线改完直接存回服务器,又明确说“不给我们开后端接口,前端自己想办法”。

这种场景大家应该不陌生 —— 传统思路是把文件丢给 LibreOffice 或 Aspose 这种服务端组件转一道,但没后端就只能走客户端方案。市面上能在浏览器里“打开 .docx → 改 → 保存”的开源库不算多,大多数要么是只读 viewer(比如 docx-preview),要么是依赖 canvas 重新画版式、改完保存出去对不上 Word 排版。

直到我翻到 docx-editor,这个项目一上来就标着“.docx in, .docx out”——解析 OOXML 后用 ProseMirror 做编辑器、保存时再序列化回 OOXML,真正在浏览器里完成 Word 文档的“读、改、写”全链路,后端零依赖。更关键的是,它同时给了 React 适配器和 Vue 3 适配器,API 名字、props 几乎一一对应,这在文档编辑器里非常少见。如果你团队两个框架都有人,或者在从 React 迁到 Vue(反过来也一样),这个特性值千金。

下面就把这个项目展开讲讲,以及集成时容易踩的几个坑。

docx-editor 官网首页
docx-editor 官网首页

核心特性

虽然定位是“在浏览器里编辑 .docx”,但它的功能覆盖比想象中全:

  • 纯客户端解析 OOXML:解析、渲染、序列化全在浏览器里,没有 server 依赖。隐私数据不出浏览器,部署就是丢一个静态包。
  • 同一份 core,两个框架适配器:@eigenpal/docx-editor-react@eigenpal/docx-editor-vue 共享 @eigenpal/docx-editor-core,在同一个项目里装两个不会重复打包解析器。props 名称、回调签名一致,文档也是两份但讲同一个东西。
  • 表格 / 图片 / 富文本格式:支持单元格合并、边框、图文环绕、字体、颜色、字号等基础排版,模板里需要的“标题 + 表格 + 签字栏”这类结构都能稳定还原。
  • Track Changes(修订模式):插入/删除会带着作者标记写入文档,工具栏可以单条接受/拒绝,或者一键全接受。法律合同、合同审批场景刚需。
  • 批注与回复:选中文字留批注、回复、resolve,状态由受控 props 管,可以挂到 Y.Array 上做多端同步。
  • i18n:官方提供 i18n 包,导入 locale JSON 就能把工具栏的 tooltip、菜单全本地化,英文 / 中文 / 日文都现成。
  • 实时协作(Yjs):把 DocxEditor 绑到一个 Yjs Y.Doc 上,光标、presence、批注就自动同步。底层 provider 自己选 —— y-webrtc 零基建、PartyKit / Liveblocks / Hocuspocus 上生产都行。
  • Agent SDK(2025 新增):@eigenpal/docx-editor-agents 提供 useDocxAgentTools Hook 和 MCP Server,可以让 AI Agent 直接在编辑器里改文档,适合做 AI 助手场景。

授权上是 Apache 2.0,个人和商用都可以,无水印、无使用上限、无 premium 收费挡板。目前 GitHub 上 1.6k star,旧包 @eigenpal/docx-js-editor 单月下载 82.4k,在 .docx 解析这个细分领域属于第一梯队的活跃度。

docx-editor 编辑器 demo 截图
docx-editor 编辑器 demo 截图

快速上手

下面分别贴 React 和 Vue 3 的最小集成示例。两个版本做的事完全一样:拿到文件 → 转 ArrayBuffer → 丢给  <DocxEditor>

React 一行挂载

import { useState } from 'react';
import { DocxEditor } from '@eigenpal/docx-editor-react';
import '@eigenpal/docx-editor-react/styles.css';

export function App() {
  const [buffer, setBuffer] = useState<ArrayBuffer | null>(null);

  return (
    <>
      <input
        type="file"
        accept=".docx"
        onChange={async (e) =>
          setBuffer((await e.target.files?.[0]?.arrayBuffer()) ?? null)
        }
      />
      {buffer && <DocxEditor documentBuffer={buffer} mode="editing" />}
    </>
  );
}

Vue 3 一行挂载

<script setup lang="ts">
import { ref } from 'vue';
import { DocxEditor } from '@eigenpal/docx-editor-vue';
import '@eigenpal/docx-editor-vue/styles.css';

const buffer = ref<ArrayBuffer | null>(null);

async function loadFile(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0];
  buffer.value = file ? await file.arrayBuffer() : null;
}
</script>

<template>
  <input type="file" accept=".docx" @change="loadFile" />
  <DocxEditor v-if="buffer" :document-buffer="buffer" mode="editing" />
</template>

如果你的项目用 Vite,装完就能跑;Next.js / Nuxt 这种带 SSR 的框架,需要再读下面“注意事项”那一节。

包结构(按需安装)

1.x 版本把原来 @eigenpal/docx-js-editor 这个单体包拆成了一组小包(原包已 archive,新项目请直接走下面的 1.x 系列),这是新装项目最容易迷路的地方:

新项目直接装对应的适配器包就行,core 会被作为依赖自动拉进来。不要再去装 @eigenpal/docx-js-editor,那个是 0.x 时代的单包,官方已经在归档,新代码不会再合进去,老项目的迁移路径官方提供 codemod。

集成注意事项

按踩坑频率从高到低列几个,生产前最好过一遍:

  • SSR 框架必须 client-only。ProseMirror 在 mount 时会读 DOM 测量,SSR 阶段没有 DOM 会炸。Next.js 用 next/dynamic 配合 ssr: false,或者把组件标 'use client';Nuxt 用 包裹,或者直接装 @eigenpal/nuxt-docx-editor 让它帮你处理。包内的 examples/nextjsexamples/nuxt 目录是最佳参考。
  • 同一项目里 React 和 Vue 可以共存。两个适配器共享 core,装两份不会重复解析器,文档 buffer 直接透传。如果你在做“老 React 模块里嵌一个 Vue 编辑器”这种事,这条就够了。
  • Track Changes 与协同是两条独立的开关mode="editing" 是基础编辑模式,track changes 是 ProseMirror 层面的 mark,real-time 协作需要你再绑 Yjs。这三者不要混淆,出问题先看 mode 和是否绑了 Yjs。
  • i18n 走 props,不是全局状态。语言包通过 i18n prop 传,不是 Context/Pinia。这点跟大多数 UI 库习惯不一样,接入时多看一眼。
  • 样式必须显式 import@eigenpal/docx-editor-react/styles.css(或 -vue)不是 side-effect import 默认拉,漏了这一步页面会变成纯白底,工具栏也没了。

适用场景

比较适合:

  • 产品里需要“在线编辑合同 / 报告 / 模板”功能,又不想自己造 Word 解析器
  • 团队 React / Vue 都用,需要统一编辑器体验
  • UI 需要多语言(尤其小语种,官方 i18n 包覆盖挺全)
  • 数据敏感、不希望文档经过第三方服务器

不一定适合:

  • 需要 PDF 导出能力 —— docx-editor 不做 PDF,要的话接 docx-pdf 之类
  • 只需要纯文本 / Markdown 编辑 —— 杀鸡用牛刀,TipTap / Lexical 这种轻量富文本更合适
  • 需要兼容 .doc(老版 Word 二进制格式)—— docx-editor 只支持 .docx(OOXML)

免费开源说明

docx-editor 是一个开源项目,采用的是 Apache License 2.0,这意味着:

  • 商业项目可用,无需付费
  • 可以修改源码、闭源分发(只要带上协议声明、保留版权头)
  • 不用为作者署名(不过保留 LICENSE 文件是行规)
  • 没有使用次数 / 用户数 / 功能档位限制

唯一的“小坑”是命名:它有 0.x 时代的旧包 @eigenpal/docx-js-editor(已 archive)和 1.x 的新包组(命名带 docx-editor),认准 docx-editor 系列就行。

写在最后

如果你和我一样被“前端编辑 .docx 又没后端”这种需求卡过,docx-editor 是目前少有的“完整覆盖”选项 —— 解析、编辑、保存、协同、AI 全包,React 和 Vue 都能直接用,Apache 2.0 商用无门槛。集成成本基本就是装包、import 样式、处理 SSR 这一套,半小时能跑通最小 demo。

docx-editor 官方文档页面截图
docx-editor 官方文档页面截图

更多细节直接看官方文档GitHub 仓库,Live Demo 也有,可以直接打开 .docx 来试试操作手感。