← На главную

Pierre выкатил CodeView:Inverse Sticky Technique для гигантских диффов

29.05.2026 19:04 · hackernews

Ты открываешь пул-реквест и ждёшь, что поймёшь, что изменилось. С небольшими правками всё хорошо. Но когда код сгенерировал агент — вместе с тестами, фикстурами и снепшотами — обзорная поверхность начинает деградировать. Браузер тормозит, навигация по файлам лагает, каждый файл загружается отдельно.

Шесть месяцев назад команда Pierre выпустила Diffs — библиотеку, которая должна была решить эту проблему и позволить разработчикам думать только о логике ревью, а не о рендеринге. Сначала сделали компоненты File и FileDiff, потом добавили простой виртуализатор и вынесли подсветку синтаксиса в веб-воркеры. Но это помогало лишь до определённого размера диффа.

Новый компонент называется CodeView. Его строили вокруг амбициозной цели: «ты должен иметь возможность просто отрендерить любой дифф». Не буквально любой — у браузера есть физические ограничения. Но на практике Pierre подошли очень близко.

Основная инновация — Inverse Sticky Technique. Обычная виртуализация рендерит только то, что рядом с областью просмотра, но при быстром скролле или прыжке по скроллбару JS не успевает обновить контент, и пользователь видит пустоту. Pierre придумали хитрость: они инвертировали поведение sticky-позиционирования. Нижний край отрендеренной области прилипает к низу вьюпорта, когда ты прокручиваешь дальше, а верхний край — к верху, когда скроллишь назад. Это сохраняет нативный скролл, но пустота не появляется — контент просто «приклеивается» к краю.

Дальше занялись масштабированием. Диффы — это не просто строки. Нужно считать высоту каждого файла, учитывать метаданные ханков, поддерживать навигацию. Для огромных наборов изменений старый подход с линейным поиском начала видимого диапазона становился тормозным. Добавили кэшированные чекпоинты и бинарный поиск — так поиск нужной строки перестал начинаться с нуля.

Чтобы избежать дёрганий скролла при изменении высоты контента, в CodeView отключили встроенный scroll anchoring браузера (overflow-anchor: none) и реализовали свой. Перед каждым обновлением DOM система запоминает, какой файл или строка сейчас на виду, фиксирует её смещение, применяет изменения, замеряет расхождения и, если нужно, корректирует позицию скролла.

С памятью тоже поработали. Парсинг гигантского патча — например, диффа между Linux v6 и v7 — может давать строки, которые неявно держат ссылку на оригинальный гигантский буфер. Pierre заставили парсер принудительно копировать нужные строки, открепляя их от исходника. Это снизило потребление памяти на том самом Linux-диффе с 2,4 ГБ до 1,15 ГБ, а время парсинга упало на 80%.

DOM-элементы не уничтожаются при скролле — они попадают в пул и переиспользуются. Это уменьшает нагрузку на сборщик мусора и ускоряет появление нового контента. Настройки отображения (сплит/юнифайд, номера строк, перенос) теперь хранятся не на каждом файле, а в общем состоянии CodeView — так их смена больше не требует обхода всех десятков тысяч файлов.

Подсветка синтаксиса работает отложенно. Сначала файл рендерится как plain text, а затем воркеры с Shiki по очереди подсвечивают строки. Результаты кэшируются (LRU), доступен API для прогрева кэша, если известно, что файл вот-вот покажут.

Остались и проблемы. Safari подводит: на агрессивном скролле Inverse Sticky Technique всё ещё может дать пустоту, requestAnimationFrame там залочен на 60 Гц даже на дисплеях с высокой частотой обновления, а девтулы WebKit не позволяют нормально профилировать — в таймлайнах непонятно, что скрывается за серой категорией «other». Пока не решили проблему сериализации подсветки для файлов в десятки тысяч строк — передача данных между воркером и главным потоком становится узким горлышком, возможно, нужен серверный стриминг. Не виртуализируют горизонтальный скролл — длинные строки в минифицированном JS или CSS создают тяжёлый DOM.

В планах у Diffs — лёгкое редактирование, семантические диффы и перенос части вычислений на сервер. А пока можно зайти на DiffsHub.com и покрутить любой GitHub-дифф любого размера — почти мгновенно.

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