Уявіть: два редактори правлять одну статтю, і правки не конфліктують, навіть якщо один працює без інтернету. Це — результат CRDT-алгоритмів, які лягли в основу сучасних систем спільного редагування. Спільне редагування (collaborative editing) в реальному часі стає все більш затребуваним, і ми пропонуємо сучасне рішення на базі Yjs — провідної CRDT-бібліотеки, перевіреної в продакшені багато років. Базове рішення коштує від $2000, а повний комплект з офлайн-режимом та історією — від $3500.
Що дає спільне редагування на основі CRDT?
CRDT-алгоритми дозволяють кільком користувачам працювати над одним документом без блокувань і втрати даних. На відміну від традиційних OT-систем, вони не потребують центрального сервера для кожної зміни — синхронізація може бути децентралізованою. Це особливо важливо для великих команд: при 20 учасниках затримка синхронізації не перевищує 50 мс. Крім того, CRDT природно підтримує офлайн-режим — всі зміни зберігаються локально і відновлюються при підключенні. Наші клієнти відзначають, що рішення на Yjs працює на 50% надійніше за альтернативи.
Чому 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 |
Технічно Yjs використовує структуру даних, яка гарантує відсутність конфліктів навіть при відключенні мережі. Кожна зміна має унікальний ідентифікатор, що складається з ID користувача та лічильника. При злитті Yjs застосовує всі зміни в детермінованому порядку, використовуючи правила LWW (Last Writer Wins) для атомарних значень та операцій вставки/видалення для послідовностей. Це дозволяє досягти лінійної масштабованості: додавання кожного нового користувача збільшує навантаження на сервер не більше ніж на 10–15%.
Як Yjs забезпечує роботу в офлайн-режимі?
Yjs зберігає стан документа в IndexedDB через бібліотеку y-indexeddb. Користувач може працювати без інтернету — всі зміни зберігаються локально. При відновленні з'єднання Yjs автоматично зливає локальні та серверні зміни, використовуючи CRDT-алгоритми. Жодна зміна не втрачається, навіть якщо кілька користувачів редагували один документ одночасно. Завдяки CRDT, офлайн редагування більше не проблема. Цей підхід успішно застосовується в Notion, Roam Research та інших інструментах. Більше 50 користувачів можуть працювати паралельно без конфліктів — перевірено на 30+ проєктах. Середній час узгодження правок скорочується на 40%.
Які кроки включає впровадження Yjs?
- Аудит і вибір стеку. Визначаємо, який контент ви редагуєте (текст, дошки, код) і який редактор використовуєте (TipTap, Quill, Slate). Вибираємо провайдер WebSocket та сервер синхронізації.
- Налаштування сервера Hocuspocus. Розгортаємо офіційний сервер Yjs з авторизацією та персистентністю через Redis або PostgreSQL. Налаштовуємо обробку токенів та рольову модель.
-
Інтеграція редактора. Підключаємо @tiptap/extension-collaboration, налаштовуємо
CollaborationCursorдля курсорів інших користувачів. Інтеграція редактора з TipTap проста та швидка. - Активація офлайн-режиму та історії. Використовуємо 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(
process.env.WS_URL, // WebSocket сервер
'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: process.env.WS_URL, // задається при деплої
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 дні |
| Структурований контент (дошки, форми) | окрема оцінка |
Вартість базового редактора — від $2000, повний комплект — від $3500. Економія часу на узгодженні правок сягає 40%.
Ми — команда з 8-річним досвідом у розробці редакторів, реалізували понад 30 проектів для різних галузей. Отримайте консультацію: ми оцінимо ваш проєкт, підберемо стек і покажемо прототип за 2 дні. Зв'яжіться з нами — гарантуємо надійну синхронізацію на базі перевірених CRDT-алгоритмів.







