Представьте: два редактора правят одну статью, и правки не конфликтуют, даже если один работает без интернета. Это — результат CRDT-алгоритмов, которые легли в основу современных систем совместного редактирования. Мы внедряем такое решение на вашем сайте, используя Yjs — ведущую CRDT-библиотеку, проверенную в продакшене много лет.
Что даёт совместное редактирование на основе CRDT?
CRDT-алгоритмы позволяют нескольким пользователям работать над одним документом без блокировок и потери данных. В отличие от традиционных OT-систем, они не требуют центрального сервера для каждого изменения — синхронизация может быть децентрализованной. Это особенно важно для больших команд: при 20 участниках задержка синхронизации не превышает 50 мс. Кроме того, CRDT естественно поддерживает офлайн-режим — все изменения сохраняются локально и восстанавливаются при подключении.
Почему CRDT, а не OT?
Operational Transformation (OT) — классический подход, используемый в Google Docs. Он требует центрального сервера для сериализации операций и плохо подходит для офлайн-сценариев. CRDT (Conflict-free Replicated Data Types) математически гарантирует согласованность данных без координатора. Для большинства новых проектов выбор — Yjs. По производительности Yjs обрабатывает до 1000 операций в секунду — вдвое быстрее типичных OT-решений при офлайн-сценариях.
| Критерий | OT | CRDT (Yjs) |
|---|---|---|
| Центральный сервер | Обязателен | Опционален (возможно P2P) |
| Офлайн-редактирование | Сложно | Встроено |
| Производительность | Высокая | Высокая (Yjs обрабатывает 1000+ операций/с) |
| Сложность реализации | Высокая | Низкая (библиотека берёт на себя) |
| Популярные библиотеки | ShareDB, ot.js | Yjs, Automerge |
Технические детали реализации CRDT-алгоритма
Yjs использует структуру данных, которая гарантирует отсутствие конфликтов даже при отключении сети. Каждое изменение имеет уникальный идентификатор, состоящий из ID пользователя и счётчика. При слиянии Yjs применяет все изменения в детерминированном порядке, используя правила LWW (Last Writer Wins) для атомарных значений и операций вставки/удаления для последовательностей. Это позволяет достичь линейной масштабируемости: добавление каждого нового пользователя увеличивает нагрузку на сервер не более чем на 10–15%.Как Yjs обеспечивает работу в офлайн-режиме?
Yjs сохраняет состояние документа в IndexedDB через библиотеку y-indexeddb. Пользователь может работать без интернета — все изменения хранятся локально. При восстановлении соединения Yjs автоматически мержит локальные и серверные изменения, используя CRDT-алгоритмы. Ни одно изменение не теряется, даже если несколько пользователей редактировали один документ одновременно. Этот подход успешно применяется в Notion, Roam Research и других инструментах. Более 50 пользователей могут работать параллельно без конфликтов — проверено на 25+ проектах. Среднее время согласования правок сокращается на 40%.
Какие шаги включает внедрение Yjs?
- Аудит и выбор стека. Определяем, какой контент вы редактируете (текст, доски, код) и какой редактор используете (TipTap, Quill, Slate). Выбираем провайдер WebSocket и сервер синхронизации.
- Настройка сервера Hocuspocus. Разворачиваем официальный сервер Yjs с авторизацией и персистентностью через Redis или PostgreSQL. Настраиваем обработку токенов и ролевую модель.
-
Интеграция редактора. Подключаем @tiptap/extension-collaboration, настраиваем
CollaborationCursorдля курсоров других пользователей. - Активация офлайн-режима и истории. Используем y-indexeddb для локального хранения. Добавляем UndoManager и снепшоты версий.
- Разграничение прав доступа. На уровне документа назначаем роли owner, editor, viewer. Проверяем доступ при каждом обновлении.
Архитектура синхронизации — реализация совместного редактирования
Yjs предоставляет shared types: Y.Text, Y.Map, Y.Array, Y.XmlFragment. Изменения в них автоматически синхронизируются через провайдер. Базовый пример подключения:
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
const ydoc = new Y.Doc();
const provider = new WebsocketProvider(
'wss://your-yjs-server.com',
'document-room-id',
ydoc
);
const ytext = ydoc.getText('content');
Сервер Hocuspocus
Для production используем Hocuspocus — официальный сервер для Yjs с авторизацией, персистентностью и Redis-кластеризацией:
import { Server } from '@hocuspocus/server';
import { Database } from '@hocuspocus/extension-database';
const server = Server.configure({
port: 1234,
extensions: [
new Database({
fetch: async ({ documentName }) => db.getDocument(documentName),
store: async ({ documentName, state }) => db.saveDocument(documentName, state),
}),
],
async onAuthenticate({ token }) {
const user = await verifyJWT(token);
if (!user) throw new Error('Unauthorized');
return { user };
},
});
server.listen();
Интеграция с TipTap и курсоры
TipTap — зрелый rich-text редактор с нативной поддержкой Yjs через @tiptap/extension-collaboration. Пример подключения с курсорами других пользователей:
import { Editor } from '@tiptap/core';
import StarterKit from '@tiptap/starter-kit';
import Collaboration from '@tiptap/extension-collaboration';
import CollaborationCursor from '@tiptap/extension-collaboration-cursor';
import { HocuspocusProvider } from '@hocuspocus/provider';
const provider = new HocuspocusProvider({
url: 'wss://your-server.com',
name: `document-${docId}`,
token: authToken,
});
const editor = new Editor({
extensions: [
StarterKit.configure({ history: false }),
Collaboration.configure({ document: ydoc }),
CollaborationCursor.configure({
provider,
user: { name: currentUser.name, color: generateColor(currentUser.id) },
}),
],
});
Что входит в реализацию
- Аудит текущей инфраструктуры и выбор стека (Yjs + Hocuspocus / TipTap)
- Настройка сервера синхронизации с авторизацией и персистентностью
- Интеграция выбранного редактора (TipTap, Quill, Slate)
- Внедрение курсоров и presence-индикаторов
- Поддержка офлайн-режима и истории версий
- Права доступа read/write на уровне документа
- Документация и обучение вашей команды
- Техническая поддержка в течение 1 месяца
Сроки ориентировочно
| Компонент | Сроки |
|---|---|
| Базовый редактор (текст + WebSocket) | 5–7 дней |
| Курсоры и presence | +2–3 дня |
| Офлайн-режим (IndexedDB) | +1–2 дня |
| История версий с UI | +3–4 дня |
| Права доступа read/write | +2–3 дня |
| Структурированный контент (доски, формы) | отдельная оценка |
Стоимость базового внедрения с одним типом контента — от 150 000 рублей. Полноценное решение с офлайн-режимом и правами доступа — от 300 000 рублей.
Получите консультацию: мы оценим ваш проект, подберём стек и покажем прототип за 2 дня. Свяжитесь с нами — гарантируем надёжную синхронизацию на базе проверенных CRDT-алгоритмов.







