Headless Univer

Headless Univer — среда выполнения Univer для работы с содержимым без интерактивного интерфейса редактора. Она использует общие с браузерным редактором модели, команды, вычисления и Facade API. Обработка возможна в Node.js и в браузере без UI. Доступные возможности определяются зарегистрированными плагинами продуктов и функций.

В Node.js можно создавать и загружать документы, менять абзацы, текст, структуру и стили, сохранять снимки Univer. Таблицы, списки, колонки, формулы и фигуры требуют своих плагинов содержимого. Изменение содержимого не создаёт изображение страницы.

Пример использует режим плагинов. @univerjs/core и плагины содержимого продукта входят в Headless; @univerjs/ui, пакеты продукта *-ui и стандартные браузерные пресеты сюда не входят. @univerjs/engine-render остаётся общей зависимостью без создания Canvas и монтирования редактора. См. границы пакетов Headless.

Локальные снимки не требуют сервиса совместной работы. Совместный пример дополнительно требует клиента, сервера и аутентификации. Для конвертации Office и снимков экрана нужны соответственно Server SDK и среда рендеринга. Импорт /facade сам по себе не регистрирует плагины и не превращает UI API в Headless API.

Установка

Shell
pnpm add @univerjs/core @univerjs/engine-render @univerjs/engine-formula @univerjs/docs

Использование

TypeScript
import { LocaleType, Univer } from '@univerjs/core'import { FUniver } from '@univerjs/core/facade'import { UniverDocsPlugin } from '@univerjs/docs'import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula'import { UniverRenderEnginePlugin } from '@univerjs/engine-render'import '@univerjs/docs/facade'const univer = new Univer({  locale: LocaleType.RU_RU,  locales: {    [LocaleType.RU_RU]: {},  },})univer.registerPlugin(UniverRenderEnginePlugin)univer.registerPlugin(UniverFormulaEnginePlugin)univer.registerPlugin(UniverDocsPlugin)const univerAPI = FUniver.newAPI(univer)univerAPI.createDocument({})

Пример совместного редактирования в Node.js

Node.js может работать как клиент совместного редактирования: загружать существующий документ с сервера, изменять его содержимое через API Facade и синхронизировать изменения с другими клиентами, открывшими тот же документ. Перед запуском подготовьте сервис совместного редактирования, клиентскую лицензию и ID доступного документа.

Файлы примера

Расположите файлы следующим образом:

text
src/docs/node/├── main.ts└── univer.ts
  • univer.ts: создаёт Univer и регистрирует плагины функций документов, расширения Facade и клиент совместного редактирования Node.js.
  • main.ts: загружает документ для совместного редактирования и демонстрирует API абзацев, текста, колонтитулов, блоков примечаний, блоков кода, цитат, списков, фигур, таблиц и колонок.

Замените your-license, адрес сервера и Cookie в univer.ts, а также ID документа в main.ts.

TypeScript
import { UniverCollaborationPlugin } from '@univerjs-pro/collaboration'import { UniverCollaborationClientPlugin } from '@univerjs-pro/collaboration-client'import {  NodeCollaborationSocketService,  UniverCollaborationClientNodePlugin,} from '@univerjs-pro/collaboration-client-node'import { UniverDocsCalloutPlugin } from '@univerjs-pro/docs-callout'import { UniverDocsCodePlugin } from '@univerjs-pro/docs-code'import { UniverDocsColumnPlugin } from '@univerjs-pro/docs-column'import { UniverDocsLatexPlugin } from '@univerjs-pro/docs-latex'import { UniverDocsListPlugin } from '@univerjs-pro/docs-list'import { UniverDocsQuotePlugin } from '@univerjs-pro/docs-quote'import { UniverDocsReferencePlugin } from '@univerjs-pro/docs-reference'import { UniverDocsShapePlugin } from '@univerjs-pro/docs-shape'import { UniverDocsTablePlugin } from '@univerjs-pro/docs-table'import { UniverLicensePlugin } from '@univerjs-pro/license'import {  IAuthzIoService,  IImageIoService,  IMentionIOService,  IUndoRedoService,  LocaleType,  Univer,} from '@univerjs/core'import { UniverDocsPlugin } from '@univerjs/docs'import { UniverDocsDrawingPlugin } from '@univerjs/docs-drawing'import { UniverDocsHyperLinkPlugin } from '@univerjs/docs-hyper-link'import { UniverDrawingPlugin } from '@univerjs/drawing'import { UniverRenderEnginePlugin } from '@univerjs/engine-render'import { UniverNetworkPlugin } from '@univerjs/network'import { UniverThreadCommentPlugin } from '@univerjs/thread-comment'import '@univerjs/docs/facade'import '@univerjs/docs-drawing/facade'import '@univerjs-pro/docs-shape/facade'import '@univerjs-pro/docs-callout/facade'import '@univerjs-pro/docs-reference/facade'import '@univerjs-pro/docs-code/facade'import '@univerjs-pro/docs-list/facade'import '@univerjs-pro/docs-quote/facade'import '@univerjs-pro/docs-table/facade'import '@univerjs-pro/docs-column/facade'import '@univerjs-pro/docs-latex/facade'import '@univerjs-pro/collaboration-client/facade'export function createUniverOnNode(): Univer {  const univer = new Univer({    locale: LocaleType.RU_RU,    locales: {},    override: [      [IAuthzIoService, null],      [IUndoRedoService, null],      [IMentionIOService, null],    ],  })  univer.registerPlugin(UniverLicensePlugin, {    license: 'your-license',  })  univer.registerPlugin(UniverRenderEnginePlugin)  univer.registerPlugin(UniverThreadCommentPlugin)  univer.registerPlugin(UniverDrawingPlugin, {    override: [[IImageIoService, null]],  })  univer.registerPlugin(UniverDocsPlugin)  univer.registerPlugin(UniverDocsDrawingPlugin)  univer.registerPlugin(UniverDocsHyperLinkPlugin)  univer.registerPlugin(UniverDocsReferencePlugin)  univer.registerPlugin(UniverDocsCalloutPlugin)  univer.registerPlugin(UniverDocsCodePlugin)  univer.registerPlugin(UniverDocsListPlugin)  univer.registerPlugin(UniverDocsQuotePlugin)  univer.registerPlugin(UniverDocsShapePlugin)  univer.registerPlugin(UniverDocsTablePlugin)  univer.registerPlugin(UniverDocsColumnPlugin)  univer.registerPlugin(UniverDocsLatexPlugin)  registerCollaborationPlugins(univer)  return univer}function registerCollaborationPlugins(univer: Univer): void {  const serverUrl = 'https://your-univer-server.example.com'  univer.registerPlugin(UniverNetworkPlugin)  univer.registerPlugin(UniverCollaborationPlugin)  univer.registerPlugin(UniverCollaborationClientPlugin, {    socketService: NodeCollaborationSocketService,    enableOfflineEditing: false,    enableSingleActiveInstanceLock: false,    snapshotServerUrl: `${serverUrl}/universer-api/snapshot`,    collabSubmitChangesetUrl: `${serverUrl}/universer-api/comb`,    collabWebSocketUrl: `${serverUrl}/universer-api/comb/connect`,    wsSessionTicketUrl: `${serverUrl}/universer-api/user/session-ticket`,    uploadFileServerUrl: `${serverUrl}/universer-api/stream/file/upload`,    signUrlServerUrl: `${serverUrl}/universer-api/file/{fileID}/sign-url`,    downloadEndpointUrl: serverUrl,    authzUrl: `${serverUrl}/universer-api/authz`,    sendChangesetTimeout: 200,    retryConnectingInterval: 1000,    customHeaders: {      // Пример: если сервер Univer использует аутентификацию через Cookie, задайте здесь заголовок 'cookie'.      cookie: 'your-cookie',      // ... другие заголовки    },  })  univer.registerPlugin(UniverCollaborationClientNodePlugin)}

Примечания по запуску

loadDocAsync() загружает существующий документ с сервера, поэтому вызывать createDocument() не требуется. Сервис совместного редактирования определяет пользователя и проверяет права по данным аутентификации, например Cookie в customHeaders. Сервер возвращает memberID соединения.

В примере отключены офлайн-кеш браузера и блокировка экземпляра между вкладками, поэтому вызывать setCurrentUser() для разделения кеша по учётным записям не нужно. Если позже понадобятся функции, зависящие от локального текущего пользователя, например комментарии, его можно задать через UserManagerService. Это не заменяет серверную аутентификацию.

Пример колонтитулов применим только к документам с разбивкой на страницы, а пример колонок — только к современным документам. Пример проверяет режим документа через isModern() и пропускает неподдерживаемые операции.

Пример вставляет содержимое в существующий документ, поэтому рекомендуется использовать тестовый документ. После выполнения пример сохраняет соединение совместного редактирования. Откройте тот же документ в браузере, чтобы увидеть изменения. flush() ожидает подтверждения сервера для изменений в очереди. Для одноразового скрипта вызовите univer.dispose() после завершения всех асинхронных операций и синхронизации.

Насколько полезно это руководство?

© 2026 DreamNum Co., Ltd.