← На главную

CodeMirror перешла на центральный сервер и жертвует идеальной синхронизацией ради скорости

03.05.2026 17:39 · hackernews

Команда разработчиков CodeMirror представила архитектуру новой версии редактора кода, которая впервые включает встроенную поддержку совместной работы. Основная сложность заключалась в том, что большинство современных редакторов используют централизованный подход: клиенты общаются с сервером, который решает, какие изменения применять. Изначально разработчики рассматривали полностью распределённую модель, где равные партнёры обмениваются обновлениями напрямую. Однако распределённый подход слишком усложняет ядро на базе JavaScript, поэтому выбор пал на вариант с центральным оркестратором. Это означает, что 95% научных публикаций про децентрализацию были в данном случае нерелевантны.

Для объединения изменений из разных источников использовали Operational Transformation (OT). В её основе лежит функция трансформации, которая принимает два изменения и создаёт их модифицированные версии так, чтобы они применялись в правильном порядке и приводили к одному итоговому документу. Это работает как перемещение одной операции через другую: если кто-то вставил текст, а потом другой пользователь удалил часть оригинала, индексы первой операции нужно скорректировать. Система работает в строгом порядке: сервер принимает изменения или отклоняет их, если база не совпадает с текущей. При получении удалённых изменений локальные операции трансформируются и применяются, после чего хранятся обновлённые версии. Такой подход гарантирует сходимость, так как все клиенты последовательно применяют одни и те же изменения.

Альтернативой OT являются Conflict-free Replicated Data Types (CRDTs). Они позволяют применять изменения в любом порядке, присваивая каждому символу уникальный ID. Однако реализация CRDT требует сохранения метаданных для каждого символа даже после удаления, что резко увеличивает потребление памяти и усложняет интерфейс. Команда решила не внедрять CRDT внутрь структуры данных редактора, чтобы не жертвовать поддержкой огромных файлов и простотой разработки, хотя внешнее подключение к реализации вроде Yjs остаётся возможным.

Ключевой особенностью нового дизайна стал отказ от работы с отдельными изменениями в пользу наборов изменений. Вместо последовательности вставок и удалений, которые сдвигают индексы, изменения хранятся как плоская последовательность неизменённых и заменяемых блоков. Так пользовательский запрос «окружить текст скобками» описывается не как две отдельные операции с меняющимися индексами, а как единый набор действий с диапазонами.

Ещё одна проблема — отслеживание позиции курсора или диапазонов кода при удалении текста. Если пользователь удаляет символы под курсором, его позиция должна измениться. В OT-системах без использования CRDT невозможно гарантировать сходимость самих позиций, так как информация внутри удалённых диапазонов теряется. Разработчики признали невозможностью сделать позиции сходящимися в классической OT без хранения «могильников» удалённого контента. Хотя CRDT решают эту проблему благодаря уникальным ID, их накладные расходы на память оказались слишком высоки. Итоговая архитектура выбрана с умением жертвовать идеальной конвергенцией позиций ради производительности и простоты.

Читать оригинал →