Вырезаем SSR и ускоряем Хабр в 10 раз

    Здравствуйте, меня зовут Дмитрий Карловский и я… тот ещё токсичный перец. Недавно я источал свои альфа-флюиды на Альфа-банк. Ребята в ответ поступили достойно, и не стали атаковать меня в личку объяснениями, как сильно я не прав, а завели задачу на гитхабе. И даже что-то пофиксили, сделав часть моих претензий несостоятельными. Но не ту часть, где SSR портит всё.


    Время утекло, пыль улеглась, и тут история получает продолжение: недавно ко мне обратился продюсер контент-студии Хабра с предложением пропесочить их Торт. Что ж, расчехляем вентилятор!


    Да будет срач


    Сложный случай


    Возьмём, например, вот эту страницу, содержащую 2500 комментариев. Это настолько огромная страница, что если вы откроете её в Хроме, то он обрежет её уже на 1400 комментарии. Чтобы прочитать оставшиеся вам придётся открыть её, например, в Огнелисе. Причину этого оставим на совести разработчиков. Давайте лучше подумаем как этого не допустить. Но сперва проведём замеры:


    Показатель Десктопная версия (HTML) Мобильная версия (JSON) Ускоренная универсальная версия (JSON)
    Размер данных 12 MB 3.4 MB 3.4 MB
    Размер сжатых данных 1000 KB 700 KB 700 KB
    Время полной загрузки 45 s 42 s 5 s
    Время показа первого экрана 5 s 42 s 5 s
    Число DOM элементов 116K 100K < 1K
    Отзывчивость при прокрутке 700 ms не удалось замерить 30 ms
    Пересчёт лейаута 1800 ms не удалось замерить 30 ms
    Потребление памяти 800 MB 1000 MB 80 MB

    Помрёшь пока дождёшься


    Методика измерений


    • Размер данных — объём HTML или JSON выдачи. Показывается в девтулзах Хрома, если включить "широкие строки". Вес указан лишь того ресурса, что выдаёт комментарии.
    • Размер сжатых данных — то, что девтулзы показывают по умолчанию для загруженных ресурсов.
    • Время полной загрузки — время открытия всех комментариев (да, иногда Хром всё же рендерит всё — не понятно от чего зависит), обычным секундомером на глазок от нажатия F5 (или ссылки "показать комментарии") до завершения всех видимых пользователю загрузок. Кеш отключался через девтулзы.
    • Время показа первого экрана — то же, что и время полной загрузки, но дожидаясь лишь появления контента, заполняющего весь экран, что позволяет начать его читать.
    • Число DOM элементов — выводился document.getElementsByTagName('*').length в режиме наблюдения, приведено максимально наблюдаемое число.
    • Отзывчивость при прокрутке — длительность блокировки основного потока при скроллинге на одну страницу. Замерялось через профайлер.
    • Пересчёт лейаута — длительность блокировки основного потока при однократном изменении размера окна. Замерялось через профайлер.
    • Потребление памяти — объём, который показывают диспетчер задач хрома (shift+esc) для вкладки после полной загрузки.

    Для всех замеров использовался обычный домашний вайфай и ноутбук с развёрнутыми на пол экрана девтулзами. Если что-то не учёл — обязательно докопайтесь к этому в комментариях.


    Флюгегехаймен


    Предварительный анализ


    У Хабра есть две версии: десктопная и мобильная. Десктопная загружает статью со всеми комментариями единым HTML. Мобильная же поступает хитрее: сначала загружается статья в виде HTML, а по клику на кнопку "комментарии" она подгружает JSON с комментариями и рендерит их с помощью VueJS вместо статьи. Но если на комментарии зайти по прямой ссылке, то будет загружен пререндеренный HTML. Пререндеренный HTML ничем принципиально не отличается от десктопной версии, поэтому я замерял именно вариант с динамическим рендером, который отрабатывает в большинстве реальных сценариев использования.


    Как видно, вес JSON примерно в 4 раза меньше HTML. В формате Tree эти данные весили бы ещё меньше, но парсились бы дольше, ибо кастомный парсер на яваскрипте даже более простого формата всё же медленнее нативного JSON парсера. В любом случае, после сжатия, которое применяется сейчас повсеместно, разница уже не столь существенна — порядка 30%.


    Пререндеренный HTML довольно долго грузится, это связано с двумя факторами:


    1. Параллельно начинают грузиться все изображения со страницы, а это 8 мегабайт несжимаемого трафика, который капитально забивает канал. Решить эту проблему могли бы через loading="lazy", но не стали.
    2. После загрузки очередного куска HTML происходит его подклейка в общее дерево, что вызывает повторное вычисление стилей, лейаута и рендеринга. Так как стоимость этого процесса растёт по мере роста DOM, то зависимость суммарной задержки загрузки от размера HTML тут экспоненциальная. Решается только одним способом — уменьшением HTML.

    При динамическом рендеринге загрузка данных происходит быстрее, но сэкономленное время компенсируется временем на работу яваскрипта по генерации DOM дерева. В обоих случаях пользователю приходится ждать не меньше полу минуты до возможности прочитать новые комментарии, что крайне долго. Также динамический рендеринг на VueJS не прогрессивен, то есть не позволяет начать чтение контента до его полной обработки.


    Всего на страницу выводится около 100K DOM элементов. Это в среднем около 40 элементов на каждый комментарий. Всё это в памяти занимает почти гигабайт.


    Браузеру становится очень плохо от такого большого DOM дерева и он начинает серьёзно тупить. Например, обновление экрана при скроллинге, несмотря на его аппаратное ускорение, занимает 700мс. И это чисто скроллинг, без пересчёта лейаута. С ним же — почти 2 секунды. А пересчитывается лейаут почти на любое изменение DOM дерева. DevTools тоже порой сходят с ума, что осложняет профилирование.


    Дерево угнетает


    Выбор стратегии


    Основная причина тормозов — размер DOM дерева. Поэтому требуется такая реализация, которая позволит иметь на пару порядков меньшее число элементов на странице. Выпишем возможные стратегии:


    Сворачивание Паджинация Виртуализация
    Описание Ветки комментариев изначально свёрнуты и разворачиваются вручную. На одну страницу выводится ограниченное число комментариев. Чтобы увидеть остальные нужно переходить между страницами Рендерятся только комментарии, попадающие в видимую область, а остальные удаляются.
    Решается ли проблема скорости загрузки Да Да Да
    Решается ли проблема отзывчивости работы Нет, пользователь с большой вероятностью откроет много веток и получит тормоза. ### Да, размер дерева на каждой странице примерно одинаков и регулируем. Да, размер дерева зависит от размера экрана.
    Поведение браузерного поиска по странице Ищет только в развёрнутом. ### Ищет только по текущей странице. ## Ищет только по видимым комментариям. ###
    Что может вызвать раздражение пользователя Необходимость постоянно разворачивать ветки комментариев. ## Необходимость переходить между страницами. ## Трудно уследить за иерархией ответов. ### Скачки скроллбара. # Возможные скачки контента при скроллинге. ##
    Наибольший уровень недовольства пользователя ### ### ## ### ## ## ### ## #

    Выводы:


    1. Виртуализация меньше всего расстроит пользователей.
    2. Так как единовременно отображаются не все комментарии, придётся вручную реализовать поиск по всем комментариям.

    Выбор из трёх зол


    Прототипирование


    Самый простой способ воспользоваться виртуальным рендерингом — переписать страницу на $mol, что позволит нам писать код даже не думая о виртуализации, но всё равно её получить, так как в $mol она встроена под капотом.


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


    const Person = Rec({
        alias: Str,
        id: Str,
        login: Str,
        fullname: Maybe( Str ),
        avatarUrl: Maybe( Str ),
        speciality: Maybe( Str ),
    })
    
    const Comment =  Rec({
        id: Int,
        author: Maybe( Person ),
        children: List( Int ),
        isAuthor: Maybe( Bool ),
        isPostAuthor: Maybe( Bool ),
        message: Str,
        parentId: Int,
        score: Maybe( Int ),
        timeChanged: Maybe( Moment ),
        timePublished: Maybe( Moment ),
    })
    
    const Comments_response = Rec({
        comments: Dict( Comment ),
        threads: List( Int ),
    })

    Некоторые поля опциональны — в них возвращается null для сообщений, оставленных НЛО.


    Теперь мы можем легко загрузить данные, проверить их и вернуть типизированную структуру. Например, так выглядит загрузка комментариев:


    @ $mol_mem
    comments_data() {
        const uri = `https://m.habr.com/kek/v2/articles/${ this.article_id() }/comments/`
        const data = Comments_response( this.$.$mol_fetch.json( uri ) )
        return data
    }

    Хорошо, данные мы загрузили, осталось их показать. Текст статей и комментариев Хабр возвращает в виде строки, содержащей довольно разношёрстный HTML. Для его отображения воспользуемся компонентом $mol_html_view:


    <= Article $mol_html_view
        html <= article_content \
        highlight <= search
        image_uri!node <= image_uri!node \

    (Если вы не знакомы с синтаксисом view.tree, предназначенным для декларативной композиции компонент, то можете ознакомиться с кратким или полным его описанием.)


    Этот компонент берёт HTML, парсит его и для каждого элемента создаёт соответствующий $mol_view компонент, а он уже сам себя виртуализирует. Кроме того, $mol_html_view позволяет указать строку, которая будет подсвечена в тексте.


    Также нам потребовалось перегрузить метод image_uri, который вызывается для каждого IMG элемента, чтобы получить ссылку на картинку. Причина в том, что в атрибуте src в выдаче Хабра изначально находится лишь ссылка на заглушку, а реальная ссылка на изображение берётся из атрибута data-src. Поэтому реализуем этот метод так:


    image_uri( node : HTMLImageElement ) {
        return node.dataset.src || node.src || 'about:blank'
    }

    Рендеринг дерева комментариев не представляет из себя ничего особенного. Разве что мы добавим возможность сворачивать/разворачивать ветки комментариев.


    @ $mol_mem_key
    comments_visible( id : number ) : readonly number[] {
    
        if( this.comment_expanded( id ) ) {
            return this.comments_all( id )
        } else {
            return this.comments_filtered( id )
        }
    
    }

    Эта функциональность полезна и сама по себе, но нам она ещё пригодится и для поиска. Дело в том, что $mol пока ещё не умеет прокручивать скролл к заданному компоненту. Штука эта вполне реализуема, но у меня руки пока не дошли, так что если если кто-то возьмётся за это дело — было бы супер.


    А сейчас, мы, вместо прокрутки страницы между найденными постами, будем сворачивать все ветки комментариев, где искомая подстрока в тексте не встречается. Таким образом пользователь может ввести запрос и просто скроллить страницу. А при желании — развернуть ветку и почитать все ответы. Выглядит это примерно так:


    Пусть говорят


    Многие пользователи привыкли к хоткею Ctrl+F для поиска по странице, поэтому добавим плагин $mol_hotkey для его перехвата:


    plugins /
        <= Search_key $mol_hotkey
            mod_ctrl true
            key * F?event <=> search_focus?event null
        <= Theme $mol_theme_auto

    Ну а для фокусирования просто доберёмся до нужного нам компонента и скажем ему сфокусироваться:


    search_focus( event : Event ) {
        this.Search().Suggest().Filter().focused( true )
        event.preventDefault()
    }

    Обратите внимание, что мы так же добавили плагин $mol_theme_auto, который автоматически ставит светлую или тёмную тему в зависимости от предпочтений пользователя.


    Кроме того, добавим пользователю возможность вручную менять тему, разместив на тулбаре кнопку $mol_lights_toggle:


    tools /
        <= Lights $mol_lights_toggle
        <= Sources $mol_link_source
            uri \https://github.com/nin-jin/habrcomment
        <= Search $mol_search
            query?val <=> search?val \

    Заодно мы тут расположили стандартную ссылку на исходники и поисковое поле, связав его двусторонней связью с поисковым запросом.


    Наведём немного красоты, переопределив некоторые дефолтные стили, используя модуль $mol_style, который обеспечивает тайпчек и подсказки, учитывающие реальную иерархию компонент:


    $mol_style_define( $my_habrcomment , {
    
        Orig: {
            flex: {
                grow: 1,
                shrink: 0,
                basis: per(50),
            },
        },
    
        Article: {
            maxWidth: rem(60),
        },
    
        Comments: {
            flex: {
                shrink: 0,
                grow: 1,
            },
        },
    
        Comments_empty: {
            padding: rem(1.5),
        },
    
    } )

    Последним штрихом добавим поддержку оффлайна:


    include \/mol/offline/install

    Этим не хитрым кодом мы установили кеширующий Service Worker, который в случае проблем с соединением будет выдавать данные из кеша.


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


    Что ж, вот наш прототип читалки хабракомментариев и готов: https://nin-jin.github.io/habrcomment/#article=423889


    Держите букмарклет, позволяющий открывать в ней любую тяжёлую статью:


    javascript: document.location = document.location.href.replace( /\D+/ , 'https://nin-jin.github.io/habrcomment/#article=' )

    Король Брака


    Анализ прототипа


    Код исходников уложился в 400 строк, на написание которых требуется не более пары часов. По функциональности:


    • Отображение произвольной статьи с форматированием
    • Отображение дерева комментариев к статье с форматированием
    • Возможность сворачивать/разворачивать комментарии
    • Поиск по статье/комментариям с подсветкой найденного и сворачиванием лишнего
    • Работа в оффлайне
    • Поддержка тёмной/светлой тем
    • Адаптивность к размеру экрана

    Мы добились ускорения полной загрузки огромной страницы в 5 раз. А потребление памяти уменьшилось в 6 раз по сравнению с мобильной версией (и в 2 раза, если отключить виртуализацию). Для мобилок это куда актуальней, чем для десктопа. При этом мы ещё даже не приступили к собственно оптимизации кода.


    Если пошаманить можно выиграть ещё несколько секунд. Например, в наивной реализации HTML всех комментариев парсится при открытии страницы для расчёта их минимальных размеров исходя из содержимого. Однако, можно руками задать какое-то константное значение, меньше которого текст комментария точно быть не может:


    <= Message $mol_html_view
        minimal_height 60
        highlight <= search \
        html <= message \
        image_uri!node <= image_uri!node \

    Таким образом парсинг HTML будет происходить лишь при фактическом отображении. Позиция скроллбара, конечно, тогда будет рассчитываться несколько менее точно, но это не страшно.


    Итого по скорости загрузки мы получили почти десятикратное ускорение полной загрузки при сохранении времени появления контента в 5 секунд. Потребление памяти тоже уменьшилось в 10 раз.


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


    @ $mol_mem
    comments_data() {
        const search = encodeURIComponent( this.search() )
        const uri = `https://m.habr.com/kek/v2/articles/${ this.article_id() }/comments/?search=${search}`
        const data = Comments_response( this.$.$mol_fetch.json( uri ) )
        return data
    }

    Реализована сейчас, разумеется, не вся функциональность. Но всё остальное особой погоды не делает. Чтобы довести до продакшена, надо будет ещё много чего реализовать. Если кто-то готов этим заняться — можете попробовать. Правда сперва придётся договориться с руководством Хабра об использовании их API. Я пробовал несколько раз подкатить с разных сторон — никакого ответа не получил.


    Также можно заметить, что отступы вокруг разных комментариев пляшут как попало — это от того, что HTML, отдаваемый Хабром, это какая-то дичь от слова совсем: слова то в параграфах, то в дивах, то параграфов вообще нет, а абзацы разделяются переводами строк или тегом BR, что вообще вырубает виртуализацию. В общем, тут надо либо чтобы Хабр отдавал что-то единообразное и валидное, либо пилить какой-то свой нормализатор выдачи.


    $mol_html_view поддерживает сейчас лишь сравнительно небольшой набор HTML-элементов — далеко не всё, что может выдавать Хабр. Добавить поддержку остальных в принципе не сложно и она, конечно, будет расширяться по мере необходимости.


    Кроме того, есть и технические косяки:


    1. Контент при скроллинге иногда скачет — это какой-то косяк в логике виртуализации $mol_list. Не приятно, но жить можно. Как-нибудь конечно же починю.
    2. В сафари автоматически отключается виртуализация сверху, так как он не поддерживает overflow-anchor, необходимый для того, чтобы можно было менять контент сверху от видимой области без скачков видимого контента. Это означает, что страница будет открываться всё так же быстро, но по мере прокрутки вниз будет дорендеривать всё остальное содержимое, пока не отрендерит все 100K элементов, когда пользователь домотает до самого конца.

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


    Король Разработки


    Резюме


    1. SSR не быстрее грамотной реализации PWA.
    2. Вместо поддержки двух абы как слепленных реализаций для разных девайсов, лучше потратить это время на одну, но толковую и адаптивную.
    3. Выбирая между двух зол, лучше сделать шаг в сторону — возможно именно там расположилось добро.
    4. VueJS — тупит, а $mol — рулит.
    5. Браузеру становится очень плохо, когда в доме много элементалей.
    6. Стоит предпочитать те решения, что не приводят к не контролируемому увеличению числа элементалей в доме.

    Элементалекапец


    Ссылки


    1. Исходники читалки — можете заметить, что кода там всего ничего.
    2. Страница фрейморка $mol — ужаснитесь сколько всего у нас там есть.
    3. Канал с новостями о $mol и MAM — подписывайтесь, чтобы быть в курсе всего важного, что с ними происходит.
    4. Канал с видео о $mol — когда-нибудь тут появятся видео-туториалы.

    Средняя зарплата в IT

    110 500 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 7 138 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 257

      +30
      И снова мол по поводу и без… Вроде хорошо начал, отличный разбор, но вот эта говнореклама раздражает.
        +20

        А почему, собственно, нет? Как по-вашему иначе показывать преимущества инструмента, если не через подобные демонстрации?

          +21
          Ну посмотрите его предыдущий аккаунт и (особенно) комментарии. Пиар своего продукта = хорошо, спам своего продукта (с элементами other = говно) = не хорошо.
            +7

            Ну, человеку свойственно исправляться всё-таки, уже не в таких тонах говорит.
            Ну а, набрасывать на другие инструменты нужно, потому что везде только хвалебные отзывы о них. React, емнип, тоже стартовал с подобных набросов на Angular

              +4

              Изменяет. На форумах, возможно, отдельные фанаты всякое писали, но от самой команды React ничего такого не было

          +7
          Если реклама идёт одним блоком в конце, то её можно спокойно проигнорировать. Ну и как бы если человек проделал такую работу, да ещё и выложил статью, то лично я не обижусь если он в конце добавит абзац с саморекламой.
            +3
            Автор сделал крутую работу, крутой разбор. В чем проблема, что это он делал на инструменте, которые хочет попиарить?
            +3
            Зачем в читалке текст поста слева? Непривычно же. Пусть бы был как в оригинале по центру, всё равно же ограничен таким же контейнером
              +1

              В продакшен реализации слева будет ещё 1-2 панели, так что текст статьи в итоге будет как раз примерно по центру:


                +1
                На моём 1280px мониторе страница обрезается по ширине.
                  –1

                  Это буклетный дизайн. Тут 2 страницы: статья и список статей. Одна страница отображается полностью, другая — насколько влезет.

              +28

              То есть тут сравнивается виртуализация рендеринга в $mol и рендер всего и вся на VueJS?
              И делается вывод, что VueJS — плохо?


              Вот пример из Реакта, во-первых, есть новый API Concurrent Mode с асинхронным рендерингом, а во-вторых, виртуализацию не нужно писать ручками, вот популярный npm-пакет react-virtualized (vuejs тоже имеет подобное)


              Так сравните как работает виртуализация в $mol и в react-virtualized. А то получается как-то несправедливо.

                +9
                вот популярный npm-пакет react-virtualized

                Лучше react-window, она почти в 10 раз меньше и во столько же быстрее. Написан автором react-virtualized как переосмысление виртуализации для Реакта.


                А ещё есть такая штука как uni-virtualizer от Polymer, но она пока ещё в разработке, правда.

                  +1
                  Ну так сравните.
                  Автор показал как с помощью его инструмента сделать лучше.
                  Вы считаете что можно сделать лучше и по другому. Ок… Но автору это зачем?
                    +5

                    Дело не в том, что можно сделать лучше по другому, дело в выводах.


                    Автор подменил понятия виртуального рендеринга и "лучше". Как результат — добавились новые проблемы, которые, возможно, не оправдывают вложенных усилий.


                    А результат — автор делает традиционный вывод: мой колхоз — рулит, а все ваши фермеры — тупят.

                  +2

                  Интересно, а если сделать виртуальный скролл несколько иначе — в "невидимой" части показывать комментарии единым блоком текста (без кнопок, разделения на хедер-футер и прочей html-разметки), а при попадании конкретного блока с комментариями — "форматировать" его и показывать полноценной разметкой — будет ли профит?


                  Из плюсов:


                  • не надо делать свою систему поиска
                  • более friendly для ssr (если вдруг захочется индексировать по комментариям) / no-js браузеров

                  Из минусов:


                  • проблема большого количества dom-узлов не решается, а отодвигается
                  • надо колдовать с размерами "неформатированных" блоков, чтобы они были примерно того же размера, что и форматированные, чтобы избежать скачков при промотке
                    0

                    Число DOM элементов уменьшится раза в 2, но скроллинг будет сильно лагать, ибо при изменении DOM будет полный пересчёт стилей и лейаута для 50К элементов.

                      0
                      Число DOM элементов уменьшится раза в 2

                      вообще, например, для одного этого комментария используется 47 тегов, против предполагаемого одного (можно даже сам комментарий не форматировать, а ведь там тоже могут быть теги).


                      но скроллинг будет сильно лагать, ибо при изменении DOM будет полный пересчёт стилей и лейаута для 50К элементов

                      хм, да, тут не поспоришь… разве что как-то зонировать элементы используя абсолютное позиционирование (но это уже кажется переусложнением)

                        0

                        Текст комментария — это развесистый HTML. Например, в первом вашем комментарии 13 элементов в одном только содержимом.


                        Это уже виртуализация и получится.)

                          0
                          Это уже виртуализация и получится.)
                          Так предложение и было — сделать виртуализацию, но по-другому.
                            0

                            В принципе было бы круто если бы сделали "супермобильную" без разметки :)

                              0

                              Без разметки это будет XML.

                        0

                        Единый блок текста должен быстро рисоваться. Например, если открыть в браузере текст первой части "войны и мира", проблем вообще никаких нет: http://az.lib.ru/t/tolstoj_lew_nikolaewich/text_0040.shtml, хотя там почти мегабайт текста.

                        +1

                        В виртуальном варианте PgUp/PgDown не работает почему-то, а скроллить очень медленно.

                          0

                          Попробуйте кликнуть куда-нибудь в скроллящейся области, тогда эти хоткеи должны начать работать.

                            +2

                            Конечно пробовал — не работает — FF-ESR, на последнем FF заработало.

                          +8

                          Что-то эта страница на моле активно сопротивляется прокрутке в конец… И поиск работает как-то странно, больше на фильтрацию похоже.


                          Кстати, те кнопки, которые, судя по их расположению и внешнему виду, должны сворачивать-разворачивать ветку комментариев, при активной фильтрации делают какую-то ерунду.


                          И ведь не первый раз я такое вижу, когда сайт на моле рассыпается от простейших действий...

                            +3
                            Это потому что со временем накапливается ошибка и если глядеть на ползунок прокрутки слева он все время скачет вверх-вниз из-за накапливания и уменьшения ошибки расчета комментария.

                            Вообще я снимаю шляпу за рабочее решение по виртуальному скроллингу для контента произвольной высоты для веба без первоначального обсчета и рендеринга всех элементов в дом.
                              +1
                              Но разве скролл должен так себя вести? Из-за такого скроллинга нажатия на Home/End/PgUp/PgDn каждый раз приводят к непредсказуемым эффектам… И с кэшами, и без (как автор пишет ниже).
                              –12

                              Попробуйте всё же прочитать статью, которую комментируете.

                                +11

                                А что, чтение статьи как-то заставит глючный сайт заработать?

                                  –9

                                  Как минимум — вы перестанете недоумевать почему оно работает так, как работает.

                                    +16

                                    Но я недоумеваю по другому поводу: какого фига оно так работает?

                                      +10

                                      Так работает $mol. Если вы видите, что где-то лагает прокрутка, возможно это $mol


                                      Это единственное, что я усвоил ото всех евангелистов $mol'а

                                      +10
                                      Мы же пытаемся улучшить пользовательский опыт, а не писать код ради кода, так? А пользователя мало интересует что внутри, ему нужно что работало. А оно не работает.
                                      Вообразим, что мы едем на авто и оно дергается. Разве нас интересуют оправдания производителя, почему оно так себя ведет? Нет. Мы хотим просто нормально ехать.
                                        –4

                                        Лёш ну это понятно. Скроллы вообще очень нетривиальная тема. Вторая после layout. Особенно если нужно кастомное поведение.
                                        И никогда ею не была. Еще со времён флеша. Бывает так, что апробированные скрипты от признанных метров в определенных ситуациях ведут себя непредсказуемо. Поэтому так много вариантов. Дмитрий предлагает свой подход. Чем больше будет замечаний тем текущий скрипт будет лучше. Иногда пишешь какому-то автору замечания, а он не реагирует. Дмитрий всегда поясняет что и как. Попробуйте написать Kelvin Luck :)))

                                          +12

                                          В данный момент, Дмитрий не улучшает свой скрипт, а огрызается в комментариях.

                                        +8
                                        Ну почему оно так работает как раз очевидно, ведь:
                                        VueJS — тупит, а $mol — рулит.
                                  +1
                                  Возьмём, например, вот эту страницу, содержащую 2500 комментариев.
                                  На FF 79.0 + Webrender + прочие ускорители на Linux полная загрузка около 10 с.
                                    0

                                    Скорее всего вы забыли отключить сетевой кеш и браузеру не пришлось параллельно загружать 8 метров картинок.

                                      +4
                                      Сеть 50-100 МБит/с.
                                        0

                                        Тут дело не только в объёме, но и числе изображений, и ограничении браузера на число одновременных загрузок, и латентности сервера.

                                          0
                                          У браузера есть ограничение на число коннектов к домену. HTTP/2 поддерживает мультиплексирование запросов. В рамках одного коннекта, можно запрашивать все картинки одновременно, что мы и можем наблюдать в таймлайне.

                                          TTFB вроде не скачет, но, конечно, может. Если отдача файлов идет через nginx или другой адекватный веб-сервер, то у него нет блокировок и жестких ограничений по числу отдаваемых файлов, все ограничено возможностями железа.
                                            0
                                            У браузера есть ограничение на число коннектов к домену.

                                            Это давно уже решено запросам на поддомены.

                                              +1
                                              Это не решение, а усугубление проблемы, так как при повсеместном HTTPS имеется больший оверхед на соединение.
                                                0

                                                До HTTP/2 это вполне себе было решение на сайтах где большое количество картинок. И даже сейчас бывают применяются эту технику, т.к. задержки на HTTPS все равно в итоге меньше, чем блокирование в ожидании освобождении потока.

                                                +1
                                                Зачем, если есть HTTP/2? SSL/TLS-handshake большая проблема, сейчас наоборот все пытаются через один домен обработать.
                                        +4
                                        FF 77 + uBlock Origin, от нажатия на ссылку до прекращения загрузки — 14 сек. Windows 7.
                                        Не понимаю какую проблему решает автор поста.
                                          +5
                                          Проблему отдельного непроизводительного браузера.
                                            0

                                            Отлично теперь мобильный фф

                                              +1
                                              Вообще я телефон использую по прямому назначению — звонить с него.

                                              На мобильном FF открывается где-то минуты 3, периодически напоминая, что сценарий не отвечает и нужно бы закрыть это всё нафиг и забыть клиентский рендеринг как страшный сон. Так же страница частями «пропадает» при прокрутке.

                                              Если поставить галку «Версия для ПК» и убрать «m» из адресной строки — грузится за 35 секунд.
                                                +4
                                                Вообще я телефон использую по прямому назначению — звонить с него.

                                                Хм, а кто, когда и на каких основания решил что вот прямо всегда, для всех и на все времена основное назначение смартфона это с него звонить? :)

                                                P.S. И нельзя ли подать аппеляцию с просьбой пересмотреть этот пункт? :)
                                                  0
                                                  Общество пользователей телефона по назначению с вашей аппеляцией не согласно.
                                                  ЗЫ. Тоже предпочитаю с телефона только звонить, а если приходиться пользоваться браузером, то пользуюсь десктопными версиями сайтов на мобиле с экраном в 3.5''. Как правило, они намного стабильнее и без наркоманских решений по интерфейсу.
                                                    0
                                                    Ну так «общество пользователей телефона по назначению» может телефоны использовать так как им хочется. Смартфоны то здесь причём? :)
                                                      +1
                                                      Как это при чем? Как это при чем? Я уже несколько лет не могу найти мобилу с хоролей рамой, емкой батарейкой и размером под подстаканник в машине (4'' максимум). Это точно все заговор соцюзеров и ютубвориоров:D
                                                      А вы на нас бедных и несчастных еще и аппеляцию подаете:)
                                                        0
                                                        Сочувствую. Я вот тоже не могу себе подходящий фитнес-браслет найти, а жена картину в гостинную. Но причём здесь смартфоны?
                                                          0
                                                          Так при том, что они все еще звонилки.
                                                            0
                                                            Ок. Но они скажем ещё и фонарики. И если кто-то тепрь не может найто подходящий фонарик, то опять смартфоны будут виноваты?

                                                            То есть я понимаю что ваши запросы в этом плане внезапно стали нишевыми и теперь вам сложно найти решение для ваших хотелок.

                                                            Но смартфоны в этом не виноваты. Максимум в этом виноваты производители или даже государство потому что не хотят обеспечивать вот прямо всех их хотелками.
                                                              +5
                                                              Ок. Поясню свою точку зрения с другой стороны.
                                                              В основе своей смартфон — это умный телефон, т.е. основной задачей, исходя из этимологии, является все еще звонилка. Если эта задача перестает быть основной, то это уже КПК (PDA).
                                                              Но в названии сейчас смартфон, а в реале это уже КПК с возможностью звонков. И сейчас именно умные звонилки как раз оказались нишевым продуктом. Основной рынок сейчас — это устройство для приложений и браузера, а функции звонков/смс идут уже дополнением.
                                                              В 12 году, примерно, мы шутили, что скоро будут звонить по планшетам, шутка оказалась пророческой:)
                                                                –2
                                                                В основе своей смартфон — это умный телефон, т.е. основной задачей, исходя из этимологии, является все еще звонилка.

                                                                В том то и дело что я например с этим несогласен. Основная задача телефона это звонить. Но это не значит что основная задача смартфона это тоже звонить.

                                                                И да, на мой взгляд для кучи людей возможность именно «звонить по телефонному номеру» в общем-то является опциональной и не особо то и нужна.
                                                                  +2
                                                                  Как раз именно звонить, и изначально так и было. Ориентировочно до 2007 года. С появлением ведроида и яоси, термин стало все больше и больше размываться.
                                                                  Когда звонить не является основной задачей, то это уже КПК — карманный персональный компьютер. А если точнее, то коммуникатор — кпк с возможностью звонков. Те самые первые смартфоны от коммуникаторов отличались большим уклоном в сторону звонков, в то время как коммуникаторы уходили больше в сторону работы с софтом.
                                                                  Потом коммуникаторы почти вымерли как класс, т.к. смартфоны распространились на их область применения.
                                                                  Ныне же смартфоны опять превращаются в коммуникаторы, только этот термин помнят уже лишь динозавры. В итоге 2 разных функциональных группы смартфонов имеют одинаковое название.
                                                                    0
                                                                    Изначально много что было. Но это не значит что оно так и осталось. Вещи меняются.
                                                                      +1
                                                                      Вещи меняются, названия только менять забывают. А то написано йух, а это забор.
                                                                        –1

                                                                        А вот этой претензии я вообще не понимаю. Есть телефон. Есть мобильник/сотовый/мобильный телефон. Есть смартфон. Три разных названия для трёх разных вещей.

                                                                          +1
                                                                          Вы упустили, что текущие смарты уже должны 4-е название иметь (или вернуться к старому кпк или коммунику). От мобильной связи там большинство пользуются только интернетом, т.е. роль телефона там уже вторична.
                                                                            0

                                                                            Не вижу почему это должно быть обязательно так. Для меня смартфон как изначально был "КПК с возможностью коммуникации" так им и остался.


                                                                            То есть я в какой-то момент сменил два своих гаджета, а именно КПК и мобильник, на один единственный, а именно смартфон. Но при этом КПК я пользовался вовсю, а мобильник мне был скорее навязан окружением. И смартфон для меня в первую очередь это "апгрейд" моего КПК.

                                                                              0
                                                                              Ну та же нокиа времен симбы и прочие одноклассники ее были телефонами, до кпк на той же вин мобайл они конкретно не дотягивали возможностями, хотя разработчики софта старались (первое было у друзей, второе у меня). Первый ведрофон у меня был 1.5 или 1.6. Это все еще в первую очередь телефон был, и лишь позднее они ушли к кпк. Что было потом у меня не помню. Потом был виндофон, этот уже сильно ушел от звонилки к кпк. В связи с рипом виндофонов пришлось вернуться к ведрофонам, к тому моменту они уже окончательно превратились в кпк. А я к тому моменту на телефоне пользовался только звонилкой с смсками, чеклистом, читалкой и изредка браузером, когда нужно что-то посмотреть вот прямо сейчас (на лыжах в 2007-2009 я использовал ровно тоже самое). Все остальное у меня всегда было на компе или ноуте. Только в 19 году у меня на телефоне появились карты дубльгиса, и то только ради более-менее актуальной базы магазинов, которая бывает нужна по праздникам, когда обычно посещаемые магазины или сервисы неожиданно оказываются закрыты.
                                                                              Так что для меня смартфон — это именно умный телефон. Все остальное лишь дополняет его основную функцию.
                                                                                0
                                                                                Если честно нокиевскими смартфонами я никогда не пользовался как впрочем и КПК на винмобайл. Поэтому мне сложно судить о чём вы говорите. Моим первым смартфоном был HTC(Touch если я не ошибаюсь) и он вполне себе адекватно заменял мой тогдашний КПК(уж извините, но модель не вспомню).

                                                                                Да и вообще я бы скзала что в понимании большинства людей именно смартфон это что-то без кнопок для набора текста/номера и Nokia 9000 Communicator или тот же Ericsson R380 скорее всего никто смартфоном даже и не назовёт.
                                                                                  0
                                                                                  Моим первым смартфоном был HTC(Touch если я не ошибаюсь) и он вполне себе адекватно заменял мой тогдашний КПК(уж извините, но модель не вспомню).

                                                                                  Эта линейка как раз из коммуникаторов выросла. Первое в линейке было еще на винмобайл, у меня что-то из более древних HTC было.
                                                                                  Да и вообще я бы скзала что в понимании большинства людей именно смартфон это что-то без кнопок для набора текста/номера

                                                                                  За это спасибо гуглу с яблоком. Та же Nokia N95 — это полноценный смартфон с кучей софта, как и многие более ранние их модели. Ныне же — это считается звонилкой:)
                                                                                0

                                                                                Смартфон как раз был телефоном с дополнительным софтом. А КПК с возможностью мобильных коммуникаций был коммуникатором.

                                                                    +1
                                                                    Если эта задача перестает быть основной, то это уже КПК (PDA).

                                                                    Помнится, девайс, совмещающий функции КПК и телефона пытались обозвать "коммуникатором", но не прижилось.

                                                                      0

                                                                      Оно активно использовалось, но, видимо, кто-то решил, что айфону будет проще взорвать рынок чем айкоммуникатору и даже "айкомму"

                                                                        0
                                                                        Тогда он был еще телефоном, в первую очередь. Так что очень даже адекватное название было.
                                                                        0
                                                                        Было, запамятовал уже за давностью лет.
                                                        +3

                                                        Т.е. у разрабов хабра мобильная версия тяжелее десктопной. Логика ай-ти ресурса номер один, чо :D


                                                        Могли бы просто сss десктопной версии подправить, но видимо захотели новый фреймворк вставить.

                                                          0

                                                          Всё жду, что в Firefox на Android вернут Stylus или хотя бы какой-то исполнитель произвольных скриптов, чтобы сидеть на настольном Хабре с телефона с мобильными стилями. Эх, не дождусь ведь!

                                                            0
                                                            Только недавно он оттуда пропал же, с последним обновлением, в котором произвольные расширения стало нельзя ставить.
                                                  +7
                                                  Попробовал в Сафари, реализация на $mol отрендерилась быстрее, но прокрутка можно сказать не работала вообще, и вела себя неадекватно, прыгала, и ползунок прокрутки был не в самом начале. А реализация на VueJS наоборот — рендерилась долго, но прокрутка работала относительно плавно, рендерило походу.
                                                    0

                                                    К сожалению, у меня нет макбука, чтобы это подебажить.

                                                      +4
                                                      Пробовал демки фреймворка смотреть, под сафари многие компоненты ведут себя не совсем корректно. Например, инпут с ± кнопками вообще не работает.
                                                      К сожалению, у меня нет макбука, чтобы это подебажить.
                                                      можно попробовать поднять виртуалку с макосью для таких тестов.
                                                        0

                                                        А что значит "не работает"? Кнопки не нажимаются? Или не появляются? Клавиатура не вылезает? Не меняется число?

                                                          +1
                                                          При нажатии на поле появляется + и — с двух сторон поля. При наведении на любой знак, появляется большой коричневый квадрат вокруг, при нажатии на знак ничего не происходит.
                                                          тут
                                                            0

                                                            И в консоли никаких ошибок?

                                                              0
                                                              пусто, никаких ошибок или других сообщений
                                                        +1
                                                        Вы просто не умеете виртуализацию готовить )
                                                        mixupload.com/styles/deep-house-2020/tracks
                                                        Крутите сколько влезет — страница не начнет тормозить, в сафари, хроме, фоксе — все норм.
                                                        И да, у меня богомерзкий jquery, ванила и серверсайд-рендеринг. Просто много дебага и скролл можно себе подчинить.
                                                          0

                                                          Вот это нормальное решение. Можно даже хранить по одному куску сверху и снизу в кэше. Тогда когда мы приходим к концу скролла мы отображаем из кэша а не по сети, а по сети в этот момент запрашиваем уже следущий кусок. Таким образом если пользователь скролит медленно то он вообще не увидит никаких индикаторов загрузки.

                                                            0
                                                            Вот это нормальное решение.

                                                            Врождённые проблемы с поиском никуда не денутся.
                                                              0

                                                              Вы же не загружаете весь интернет для поиска в гугле. А зачем вам грузить все тысячи комментариев для поиска по ним?

                                                                0
                                                                Но многие и не идут в гугл, если хотят что-то найти на странице. Если увидите или сделаете полноценную реализацию Ctrl/Cmd + F — буду благодарен. С подсветкой, с выводом количества совпадений и пр.
                                                                  0
                                                                  С подсветкой, с выводом количества совпадений и пр.

                                                                  В каждом браузере страны. Только от убирания DOM нод придётся отказаться ))
                                                                    0
                                                                    Ну я не исключаю что можно сделать правильную реализацию через api сайта. Но пока не видел такого (
                                                            –2
                                                            Реализуйте сперва дерево комментариев, потом поговорим о том кто и что не умеет.
                                                              +1

                                                              А зачем вам дерево? Просто посчитали один раз смещение по горизонтали и всё. Дальше комментарии идут одним списком, уже тут предлагали.

                                                                0
                                                                1. Визуализация может быть разная, не только отступ слева.
                                                                2. Высота комментариев недетерминирована.
                                                                  0
                                                                  1. Может быть, но всё равно в рамках dom можно попробовать обойтись списком.
                                                                  2. Это проблема только в древовидном dom. В линейном определить высоту прокрутки можно даже когда высота разная.
                                                                    –2

                                                                    Я смотрю тут много теоретиков, которые знают как надо, но никогда сами руками этого не делали.

                                                                      –1

                                                                      Или сделают так, что лучше бы и не делали вовсе. Но советы дают легко и непринужденно. Видимо первое что в голову придет. Поэтому я не любил олимпиады по программированию. Вроде и решил задачу, но решение далеко от канонического. На качество нужно время.


                                                                      PS: К вопросу о «теоретиках» — я в своё время делал виртуализацию ленты документов (очень произвольного размера) на vanilla JS.

                                                                      JustDont ну покажи решение того, что показывать не надо. Не стесняйся.

                                                                        0

                                                                        Ну а почему прыгает cкролл-бар? Без нашего ведома браузер может поменять шрифты (это не тот случай), и может подгрузить картинки.
                                                                        Когда подгружаются картинки, то прыгает скролл даже в статическом html. Это не возможно полностью пофиксить. Есть ли у вас другая объективная причина почему оно прыгает?

                                                                          0

                                                                          Кроме редких частных случаев, невозможно узнать высоту контента, пока весь его не отрендеришь.

                                                                            0

                                                                            А что рендеринг асинхронный? Если я удаляю или добавляю елемент сверху для экономии ресурсов, то я заменяю его на соответсвующий margin. То же самое и снизу. Кажется не надо знать всё заранее.

                                                                              0

                                                                              Я тут подумал. Вобщем без того чтобы контролировать scroll bar самому не получится сделать красиво.


                                                                              Дальше будет критика, но меня просто заинтересовала задача, так что надеюсь конструктивная.


                                                                              В вашей реализации самое странное это какие-то подергивания. Т.е. я делаю скролл вниз, браузер отрисовывает его ниже и потом он прыгает вверх и сразу вниз. Т.е. вот эти прыжки туда-сюда не понятно зачем нужны. По-идее, мы меняем высоту один раз за обработчик onscroll т.е. прыжок должен быть один. Как это происходит при бесконечной прокрутке например.


                                                                              Во-вторых, не реализовано запоминание размеров. Т.е. при повторном скролле всё опять дергается.


                                                                              Демка ngx-virtual-scroller работает плавнее, но возможно из-за того что там распределение рандомных размеров равномерное, а на хабре подругому.


                                                                              Основная проблема это то что нельзя узнать какая высота изначально. Т.е. как только мы забираем новую пачку комментариев то у нас меняется наше предсказание о том сколько места ещё надо сверху или снизу. Соответственно соотношение место вверху к месту внизу меняется. Решить это можно так: скролл бар должен быть не линейный. Сам указатель скролла мы оставляем на месте, но теперь размеры выше от него и ниже от него умножаем на соответствующий коэффициент. Его учитываем при последующей прокрутке.

                                                                                0
                                                                                1. Да, реализация не идеальная.
                                                                                2. Размеры не запоминаются так как они могут измениться как угодно, когда за ними не следишь. И если увеличение не страшно, то уменьшение может привести к скачкам контента.
                                                                                3. В демке ngx-virtual-scroller наблюдаю постоянные скачки контента при рандомных высотах.
                                                                                4. Пока скроллбар по середине не особо важны размеры отступов сверху и снизу. Проблемы начинаются, когда скроллбар достигает края. И тут все погрешности начинают стрелять по ногам. Я выбрал вариант с постоянной корректировкой положения по чуть-чуть, чем одной на несколько страниц.
                                                                                5. Есть мысль отказаться от браузерного рендеринга и рисовать всё самому — там можно довольно точно всё контролировать. Да и работать это будет раза в 2 быстрее. Но это очень далёкая перспектива.
                                                                                  0

                                                                                  Размеры меняются если комментарии добавляются или редактируются?


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


                                                                                  Корректировки это правильно. просто надо чтобы корректировки позиции для рендера и для скроллбара не были связаны. Как я предложил выше. Что думаете?

                                                                                    0

                                                                                    Они по разным причинам могут меняться. Например, при догрузке шрифта.


                                                                                    Такого не происходит в самом начале. В середине списка скачет даже при медленной промотке. Причины мне не известны.


                                                                                    Скроллбар показывает позицию вьюпорта относительно контента. Они не могут быть не связаны без деградации UX.

                                                                                      +1
                                                                                      Они по разным причинам могут меняться. Например, при догрузке шрифта.

                                                                                      На самом деле это не важно. всё равно для примерной оценки мы используем текущий размер. можно при каждом отображении обновлять кэш.


                                                                                      Скроллбар показывает позицию вьюпорта относительно контента. Они не могут быть не связаны без деградации UX.

                                                                                      UX уже деградирован. потому что если вы хотите перейти на позицию например 20% но не знаете какая реальная высота коментов. Даже приблизительные размеры не знаете, для тех которые пользователь уже видел.


                                                                                      А то что этот индикатор скачет как бешанная лошадь, вот это как по мне проблема UX. То что отображает скроллбар и так и так будет очень приблизительная оценка. Может дойдут руки и я попробую реализовать. Интересно как будет работать.

                                                                                        –1

                                                                                        По сути проблема прыгающего скроллбара сильно преувеличена. На мобилках его вообще зачастую не видно.

                                                                                          0

                                                                                          ну вот и всё))) на десктопе тоже спрятать, и вообще просто сделать свой индикатор и позицию по номеру комментария определять.

                                                                              +1
                                                                              Когда подгружаются картинки, то прыгает скролл даже в статическом html. Это не возможно полностью пофиксить.

                                                                              Достаточно указать размеры изображения в HTML. Впрочем, Firefox с этим обещал бороться, правда результата я не заметил.
                                                                                0

                                                                                Да, только картинки лепят в комментарии абсолютно разные.

                                                                                  +3
                                                                                  Если вы про конкретно Хабр, то перезагружать все на hsto, а уж договорится с ним и забирать оттуда размеры вполне себе возможно.
                                                                                    0

                                                                                    Но ведь можно сделать для комментариев 2 панели — в одной скроллится tree комментаторов, в другой их коммент

                                                                                      +2

                                                                                      вложенные скроллы так себе

                                                                            +1
                                                                            1. «Разную визуализацию» тоже ничего не мешает представлять через плоский список. Ну и YAGNI.
                                                                            2. Очень даже детерминирована. Правда, комментарий сначала придётся отрендерить, чтоб таки детерминировать, но это технические тонкости.

                                                                            PS: К вопросу о «теоретиках» — я в своё время делал виртуализацию ленты документов (очень произвольного размера) на vanilla JS.
                                                                              0
                                                                              JustDont а как быть если элементов 10к, а пользователь быстро листает? Все рендерить в дом для просчета размеров?
                                                                                0
                                                                                Если бы тут были серебряные пули — их бы уже давно все фигачили на сайтики. Увы, их в общем виде нет. Мы для наших задач реализовывали схему «поначалу может работать так себе, но потом хорошо», потому что нам надо было комфортную длительную работу с этим списком сделать — итого наши пункты списка потихоньку в фоне рендерились и замерялись. Через некоторое время замерялись все элементы, и всё начинало отображаться очень гладко, а до этого момента — ну, как повезет, скролл конечно мог вести себя довольно непредсказуемо.

                                                                                Но принципиально другого решения тут, насколько я вижу, нет. Можно конечно замерять всё на сервере через SSR, чтоб не делать это на клиенте, но это принципиально такая же схема, только ответственность по-другому разнесена.
                                                                  +10
                                                                  Вырезаем SSR и делаем смартфонам не из топовых линеек больно.

                                                                  Нет, спасибо, оставьте, пожалуйста, SSR. Я лучше подожду пока картинки прогрузятся и буду спокойно всё читать.
                                                                    +1

                                                                    На моём далеко не топовом смартфоне открытие комментариев в мобильной версии Хабра заняло несколько минут и 1% батареи. Браузерный рендеринг при этом остановился после 8 комментария. Я прождал ещё 2% батареи но так и не дождался продолжения. Ускоренная версия открылась за 10 секунд и летает.

                                                                    +4

                                                                    Скролл для элементов с динамической высотой сделать сложно, видимо поэтому он и прыгает :). Но, сказать честно, реализация могла быть и получше. Идея ведь совсем не новая, даже для хабра (см. мою статью про похожую проблему аж 2011 года: https://habr.com/ru/post/111422/)

                                                                      +2
                                                                      Возможно, можно и лучше. Проблема в том что у разработчика нет Сафари для тестирования.
                                                                      Но я вот совсем не понимаю смысла кастомного скрола и других элементов тоже. Единый стиль конечно хорошо, но тратить силы на это я бы не стал.

                                                                      Например mol_number под Сафари просто не работает.
                                                                      +25

                                                                      Вы придумали и решаете проблему, значимость которой переоценена. На Хабре мало статей с большим числом комментов, это скорее исключение, чем правило. И оптимизация таких редко встречающихся статей просто не имеет смысла.


                                                                      Вы предлагаете какое-то жутко переусложненное (тормозящий браузер клиентский рендеринг) решение, на каком-то никому неизвестном JS фреймворке, ломая стандартный функционал браузера (поиск), да еще и с самодельным кешем на Service Worker (страшная бессмысленная технология). Алло, в браузере уже есть кеш, зачем вы предлагаете делать жалкое его подобие, которое только жрет память и замедляет браузер? Всегда можно открыть about:cache или как там и просмотреть кешированную страницу. Без всяких воркеров, JS и потребления памяти, прикиньте?


                                                                      Самое быстрое и лучшее решение, на мой взгляд — просто отдавать с сервера HTML. Браузер умеет прогрессивно отображать HTML. Вы правы, что картинки стоит сделать лениво загружающимися. Но для отображения HTML нужен еще CSS, и тут разработчикам надо поработать. Надо отказаться от вредной идеи писать все стили в один файл и использовать громоздкие уродливые фреймворки вроде Bootstrap. Нужно выкинуть весь старый CSS код, начать писать для каждого компонента свой файл со стилями CSS, и к странице подключать только используемые на ней компоненты. Тогда объем CSS будет невелик (много ли CSS надо для отображения текстовой статьи? Не более 50 Кб навскидку) и страница будет загружаться быстрее. Увы, на практике почему-то встречается подход "склеиваем вебпаком все в огромный CSS на мегабайт и удивляемся, почему все тормозит".


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


                                                                      Далее, выкиньте веб-шрифты — они не нужны, но замедляют отображения текста. В современных ОС Windows и Mac уже есть хорошие шрифты.


                                                                      В общем, при моем подходе, для отображения статьи надо всего 2-4 файла — HTML и 1-3 легких CSS файла. Это решение будет грузиться быстро и обладать простой архитектурой, и не потребует разбираться в залежах JS кода.


                                                                      Также, предлагаю отказаться от метрики "время отображения первого экрана". Какой в ней смысл? Это приводит к нездоровым оптимизациям, когда первый экран грузится быстро, а все, что после него — долго. Это глупая и ненужная метрика, вы же всю статью прочесть хотите, а не первый экран (занятый шапкой и меню)? Последуйте моему совету насчет сокращения объема CSS и эта метрика вам не понадобится.


                                                                      И что за бредовая идея описывать стили внутри JS кода? CSS справляется с этим намного лучше и не требует тяжелых библиотек для работы, в отличие от JS.


                                                                      И что это за дурацкое название Maybe(Str)? Это называется Nullable(Str), а ваше название только сбивает с толку. В базе данных мы же пишем IS NOT NULL, а не IS NOT MAYBE. Зачем придумывать новые названия для существующих вещей?


                                                                      Также, откажитесь от moment.js, это тяжелая переусложненная библиотека, от которой вы будете использовать 5% функционала. Заодно откажитесь от темных тем, бессмысленная трата времени, плюс в браузере есть режим для чтения на такой случай.

                                                                        +2
                                                                        "склеиваем вебпаком все в огромный CSS на мегабайт и удивляемся, почему все тормозит".

                                                                        Интересно, а есть webpack наоборот: вырезать из кучи зависимостей и отдавать только тот CSS и HTML, что нужны?

                                                                          0
                                                                          css tree shaking
                                                                          0
                                                                          Есть. Но работает медленно. Чтобы удалить неиспользуемый css нужен готовый html. И при каждом изменении html нужно заново формировать css.
                                                                          +3

                                                                          И плюс, для реально больших развесистых комментариев можно спокойно сделать пагинацию, примерно как наши предки сделади лет так пятьсот назад, перейдя с свитка на книги

                                                                            +2
                                                                            Да такое впечатление, что все делают эти «бесконечные» страницы просто потому, что могут. Хотя пагинация позволяет отображать страницы намного быстрее, и с точки зрения юзабилити никакой разницы нет, нажать на кнопку «следующая страница» или крутнуть колесико мышки. Управление с клавиатуры? Тоже никакой проблемы, для «следующей страницы» можно добавить шорткат. Для поиска можно рядом с ссылками на страницы «1.2.3...» добавить ссылку «весь тред целиком», пусть желающие смотрят его себе целиком на здоровье.
                                                                              0

                                                                              А новые комментарии?

                                                                                0

                                                                                А это можно решить как и в бесконечном скроле кнопкой сверху "появились новые комментарии, показать?" (в ВК так сделано). Я это к тому, что и при пейджинке и при бесконечно скроллинге добавление новых сущностей сдвигает последовательность.

                                                                                  0

                                                                                  Как-то можно, наверное. Но вот при пейджнге я думаю, не очень будет удобно по одной кнопке скакать с первой страницы на 50-ю...

                                                                                    0

                                                                                    А при кролинге от первой к 50-ой переходить удобно? Скролишь и материшься… Потому что при нормально сделанном пейджинге можно ходить как последовательно "назад" и "далее" по страницам, так и задать конкретный номер сразу.

                                                                                      0

                                                                                      Никаких проблем со скроллингом на Хабре не испытывал, правда нужды перейти на "первые/семнадцатые/последние 5% комментариев" тоже не испытывал: интересует или все комментарии подряд, или непрочитанные, или поиск по ctrl+f как по содержанию, так и по метаинформации типа ника, даты и времени. Хотя вру, иногда не хватает простого способа "перейти в самое начало или самый конец комментариев без обычной клавиатуры"

                                                                                        +3
                                                                                        Проблема отображения комментариев в Хабре (и в косплеящем его в этой части DOU, как минимум), что если страница закрыта (даже случайно, ну ткнули когда не хотели в ссылку) и открыта заново, отметки читанности уже теряются. Поэтому задача всерьёз прочитать комментарии и не терять ни одного (не будем обсуждать, зачем это нужно — ну вот бывает) превращается в слишком зависящую от случайностей. А режима показа комментариев в плоском виде по порядку добавления — не делают принципиально — видимо, слишком гордясь деревом.

                                                                                        Этой проблемы нет, например, в RSDN — там есть и плоский режим с пагинацией (я почти всегда в нём), и дерево (дерево там сделано, с точки зрения современного веба, жутко топорно — для текущего комментария сделан отдельный фрейм, в который каждый раз подгружается вложенная страница с ним; но работает же...)
                                                                                          0

                                                                                          Да, есть такое. Не часто, но случается. И плоский режим помог бы при таких "форс-мажорах".


                                                                                          Boomburum что думаете?

                                                                                            +1
                                                                                            Так это ортогонально плоскому режиму, всего-то надо метки читаности куда-то чуть более надежно сохранять.
                                                                                              0

                                                                                              Плоский режим проще, по-моему, реализовать

                                                                                                0

                                                                                                Ну да, ключи искать проще там, где светло, а не где потерял.)

                                                                                              +1
                                                                                              Понравилась аналогия со свитком и книгой (выше) :) Однако в данной аналогии действительно не учитывалось то, что в момент перелистывания на страницах могут появляться новые абзацы. В целом мы не раз обсуждали переработку комментариев, есть концепты решений — если я правильно понял разработчиков, за каменты планируют взяться в начале нового года (до этого времени переписывают Хабр под единую m.версию).
                                                                              +16

                                                                              Про Maybe и Nullable это вы зря. Maybe, Just, Some, Either — это целый отдельный, дивный мир.


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

                                                                                +3

                                                                                Тут явно есть обратная связь: чем хуже Хабр работает с комментариями, тем меньше статей с комментариями.


                                                                                Кроме Windows и Mac есть ещё Linux


                                                                                Причём вообще базы данных в разговоре о фронте? В SQL и JS семантика null разная.

                                                                                  +7
                                                                                  Чистый html с ccs? Но люди же учили фрейморки (иногда вместо языков), тратили свое время и силы. Нет уж! Пусть пользователи мучаются, потому, что я знаю фреймворк.
                                                                                  –4

                                                                                  Maybe, Moment — это просто локальные алиасы:


                                                                                      const Int = $mol_data_integer
                                                                                      const Bool = $mol_data_boolean
                                                                                      const Str = $mol_data_string
                                                                                      const Maybe = $mol_data_nullable
                                                                                      const Rec = $mol_data_record
                                                                                      const List = $mol_data_array
                                                                                      const Dict = $mol_data_dict
                                                                                  
                                                                                      const Moment = $mol_data_pipe( Str , $mol_time_moment )
                                                                                    +8
                                                                                    решаете проблему, значимость которой переоценена.

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

                                                                                      На данный момент жуткие лаги при комментировании возникают не из-за отсутствия виртуализации, а из-за кривого редактора. Если отключить все обработчики нажатия клавиш (keydown, keyup и keypress) — лаги сразу же пропадают.


                                                                                      Только не спрашивайте каким таким образом скорость работы этих обработчиков зависит от числа комментариев...

                                                                                        +3
                                                                                        И решению этой проблемы без апгрейда моего железа я бы очень даже обрадовался.

                                                                                        Переход на Firefox.
                                                                                          +1
                                                                                          Увы, файрфокс у меня тоже тормозит в больших топиках.
                                                                                            +1
                                                                                            Предлагаете мне перейти с FF на FF? Отличное решение, правда проблема остается.;)
                                                                                              0
                                                                                              Просто у меня не тормозит, а ведь мой процессор это Ryzen 1200, который стоил мне около 3к рублей.
                                                                                          0
                                                                                          самодельным кешем на Service Worker (страшная бессмысленная технология).

                                                                                          Я её отключил, после того, как однажды зашёл на about:serviceworkers и увидел кучу сайтов, на которые заходил полтора раза год назад. В итоге сломалось только видео в VK, ну да не жалко, youtube-dl как ни странно справляется.
                                                                                          +1

                                                                                          Открываю ваш вариант


                                                                                          1. На вкладке сеть я вижу что текст статьи уже загрузился но мне его не показывают.
                                                                                          2. Запрос комментариев на моём дачном глючном интернете показал фигу через несколько минут.

                                                                                          В результате вместо статьи без комментариев вижу фигу с ошибкой сети. К сожалению хабр не позволяет догрузить комментарии кусочками через Range или API(или я не знаю как).

                                                                                            +1
                                                                                            1. Спасибо, поправил. Сейчас статья и комментарии должны рендериться независимо друг от друга.
                                                                                            2. Тут уже нужно изменение API, да.
                                                                                            +2
                                                                                            На Хроме на какой-то баг с бегунком для прокрутки, не получается за него нормально схватится, но в остальном в отличии от серверного рендеринга хотя бы полностью дерево рендерит (при полной прокрутке). На лисе всё хорошо. Но Лиса из-за виртуального рендеринга и оригинальную страницу более менее нормально открывает. Насчет времени, всё так — 300мс против примерно 15с на html варианте. Порадовало более менее точное определение положения скрола и нормальный скролл к самомму низу страницы сразу. После прокрутки скролл почти не дергало взад-вперед, может немного и видимо из-за картинок, попавших в подгружаемую часть. По плавности скрол версии с $mol в Firefox был сравним с скроллом html версии в Хроме, немного проигрывая только html версии в Firefox.

                                                                                            Насчет корректности сравнения $mol и Vue.js говорить не берусь, с одной стороны у Vue.js тоже есть реализации виртуального скролла. С другой в $mol виртуальный скролл входит, как я понял, в ядро и доступен «из коробки».

                                                                                            Традиционные замечания по поводу синтаксиса шаблонов, который кроме как в $mol не встречается, и по поводу использования snake_case в языке в котором вся стандартная библиотека и все популярные библиотеки написаны в camelCase, я пожалуй особо расписывать не буду, вам уже писали про них без меня. Это в конце концов ваш выбор как разработчика.
                                                                                              0
                                                                                              Шустро, в Safari на iPad, а стандартная версия ужасна.

                                                                                              Однако, на MacBook загружается тоже во много раз быстрее, но… Время пролистывания на последний комментарии получилось существенно дольше, чем полная загрузка и пролистывание старой версии.
                                                                                                +2

                                                                                                Вы забыли про блокировщики, в FF 79 полная загрузка занимает 42 с но с uBlock Origin сокращается до 21 с. Читать можно уже через 10 с, но не очень приятно из-за ресайзов от подгрузки картинок.

                                                                                                  –1
                                                                                                  отключите js, если очень уж хочется комментариев оставьте habr.com и habrcdn.net. Полетит. При этом вы ничего не теряете.
                                                                                                  +2

                                                                                                  Можно попробовать первоначально загружать комментарии без рендеринга, только текст. (По одному диву на комментарий)
                                                                                                  Комментарии, который скоро попадут в область просмотра, заменять на полноценный контент.
                                                                                                  Те, которые больше не понадобятся, заменять обратно на текст и сохранить высоту содержимого.
                                                                                                  Это решит проблемы с поиском и, по большей части, с прокруткой.

                                                                                                    +1

                                                                                                    Мне кажется, дело еще в том, что там структура тегов древовидная, тег родительского комментария содержит все дочерние комментарии. Браузеру сложнее это перерисовывать, чем если бы был плоский список, а структура комментариев регулировалась только отступами.

                                                                                                      0

                                                                                                      А вот это интересная гипотеза.

                                                                                                      +1
                                                                                                      Код исходников уложился в 400 строк, на написание которых требуется не более пары часов

                                                                                                      А это прямо ровно засеченное время на реализацию или примерное?

                                                                                                        +2
                                                                                                        Ну как раз это на мой взгляд не особо-то и принципиально. Я бы скорее спросил сколько времени автор до этого потратил на изучение инструментов и оттачивание навыков, чтобы быть в состоянии решить эту задачу всего за пару часов и уложиться в 400 строк.

                                                                                                        Вот я как бы уверен что попробуй я такое повторить и в два часа лично я вот никак не уложусь :)
                                                                                                          0

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

                                                                                                            0
                                                                                                            Но вы же согласитесь что как минимум день у меня на изучение фреймворка то уйдёт. А скорее даже и больше.

                                                                                                            П.С. И на самом деле может теперь на досуге и взгляну. Хотя в работе мне это вряд ли пригодится в ближайщее время :)
                                                                                                            +2

                                                                                                            Ну вот у меня есть сомнения, что в 2 часа реально уложиться. Более того. Возникло впечатление, что и сам автор в этот срок не уложился.

                                                                                                              0

                                                                                                              А какая разница? Время до этого вы тратите единоразово.

                                                                                                                +1
                                                                                                                Это если я им буду более-менее регулярно пользоваться то разницы нет. А вот если я им и пользуюсь всего единоразово, то… :)
                                                                                                                  0

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

                                                                                                              0

                                                                                                              Экспертная оценка.

                                                                                                                0

                                                                                                                Т.е. это не результат прямого замера, так? Это просто предположение, сколько это будет занимать у тех, кто этим начнет пользоваться.

                                                                                                                  –1

                                                                                                                  Вот тут я время замерял, если вам интересно: https://habr.com/ru/post/491120/#istoriya-uspeha


                                                                                                                  Там оказалось 2 часа на реализацию и ещё 2 пришлось подевопсить. Проработанные дизайн-макеты уже были. Повторение половины от расписанной там функциональности на высокоуровневом react-based фреймворке заняло неделю работы двух разработчиков.


                                                                                                                  Ну а если вы настолько прям сомневаетесь, то подписывайтесь на Ютуб канал, чтобы не пропустить скринкаст разработки очередного приложения.

                                                                                                              0

                                                                                                              Подскажите зачем используются атрибуты вместо классов? Что это даёт?

                                                                                                                  +2

                                                                                                                  Что такое селекторы атрибутов я знаю. У вас в HTML коде куча атрибутов без значения которые используются явно вместо классов. Разве они не раздувают DOM и HTML?


                                                                                                                  Есть ли смысл использовать атрибуты вместо классов?


                                                                                                                  Если что у классов есть удобное браузерное API которое позволяет легко их добавлять и удалять.

                                                                                                                    0

                                                                                                                    А есть ли смысл использовать классы вместо атрибутов?

                                                                                                                      +1
                                                                                                                      Скорость и семантика?
                                                                                                                        –7

                                                                                                                        Разница в скорости незначительна, семантики у классов никакой, гибкость у классов ограничена, 1 апи проще чем 2.

                                                                                                                          +5

                                                                                                                          Так какие возможности дают атрибуты по сравнению с классами?


                                                                                                                          el.hasAttribute (name) > el.classList.contains (name)
                                                                                                                          el.removeAttribute (name) > el.classList.remove(name)
                                                                                                                          el.getAttribute (name) > el.classList.contains(name)
                                                                                                                          el.setAttribute (name, str) > el.classList.add(name)


                                                                                                                          А есть ещё:
                                                                                                                          el.classList.toggle(name) — добавить или убрать класс в зависимости нет его или есть в списке соответственно.


                                                                                                                          el.classList.replace(old_name, new_name) — заменить один класс другим.


                                                                                                                          Я не говорю что нужно использовать классы вместо атрибутов. Просто не надо использовать атрибуты вместо классов.

                                                                                                                  –1
                                                                                                                  Что это даёт?

                                                                                                                  В случае с веб-компонентами даёт возможность подписываться на изменение любого свойства компонента через attributeChangedCallback, что часто очень пригождается.

                                                                                                                    –1

                                                                                                                    Ну если очень нужно отслеживать добавление и удаление элементу класса то можно отслеживать атрибут class. Он будет меняться при добавлении и удалении класса.


                                                                                                                    Разбиваем по пробелам oldValue и newValue. Чего нет из oldValue в newValue удалено. Чего нет из newValue в oldValue добавлено.

                                                                                                                      0

                                                                                                                      А затем для передачи параметра mask="99.99.9999" вы начнёте городить парсер разбирающий класс mask_99.99.9999. А ещё вдруг окажется, что к таким классам из-за значения в нём теперь не прицепить ничего из css как можно было с именем атрибута. Да и пробелы иногда нужно в значении передавать. Не придумывайте себе проблемы.

                                                                                                                        +2

                                                                                                                        Я не призываю использовать классы там где нужно использовать атрибуты.


                                                                                                                        Автор же использует атрибуты в роли классов. То есть у элементов куча атрибутов с пустыми значениями. И по именам этих атрибутов элементам задаются CSS стили.

                                                                                                                          0
                                                                                                                          Я не призываю использовать классы там где нужно использовать атрибуты.

                                                                                                                          Да даже если так, зачем создавать себе гемор вот с этим:


                                                                                                                          Разбиваем по пробелам oldValue и newValue. Чего нет из oldValue в newValue удалено. Чего нет из newValue в oldValue добавлено.

                                                                                                                          ?


                                                                                                                          Автор же использует атрибуты в роли классов

                                                                                                                          А можете привести пример когда что-то должно быть именно классом и совсем не смотрится в виде атрибута?

                                                                                                                          0
                                                                                                                          Эм, стилизация отдельно, параметры отдельно? Не пойму о чём спор.
                                                                                                                            0

                                                                                                                            Иван пытается протолкнуть идею, что булевы параметры для стилизации обязательно задавать исключительно через классы и нельзя через атрибуты. Ему объясняют, что стили необходимо привязывать не только к булевым параметрам. А разделение на булевы и не булевы не даёт ничего кроме усложнения на ровном месте.

                                                                                                                              0
                                                                                                                              булевы параметры для стилизации

                                                                                                                              Эм, стилизация отдельно, параметры отдельно? Повторяюсь, да.
                                                                                                                                0
                                                                                                                                Эм, стилизация отдельно, параметры отдельно?

                                                                                                                                Зачем отдельно? Ситуация когда на добавление/удаление какого-либо атрибута нужно и в js как-то отреагировать и какие-то стили добавить у меня происходит регулярно. По вашему же получается нужно так:


                                                                                                                                <x-dropdown class="opened" opened></x-dropdown>
                                                                                                                                  –1
                                                                                                                                  Видимо это новомодное реактивное (или как там) программирование, я такого не понимаю. Для меня есть код, который добавляет этот класс, вот там и нужно реагировать. А менять класс (или атрибут) в одном месте, чтобы в другом через слушатель отреагировать — это дичь какая-то, вот уж точно усложнение ради усложнения.