Опыт Tecnoblog в работе с комментариями Discourse

Привет!

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

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

Вот что я пока обнаружил:

1. Производительность и нагрузка на сервер

Нагрузка на наш сервер значительно возросла после того, как мы внедрили полное приложение. Судя по Cloudflare, объем наших запросов увеличился в 10 раз. Вот несколько идей по оптимизации:

  • Ленивая загрузка: Внедрение ленивой загрузки для JS очень помогает (я уже использую обходной путь для этого).
            <script type="text/javascript">
                DiscourseEmbed = {
                    discourseUrl: '<?php echo esc_url($discourse_url); ?>',
                    
                    <?php if ($use_topic_id): ?>
                        // Режим ID: Тема сохранена в базе, не подвержена изменениям URL
                        topicId: <?php echo intval($topic_id); ?>,
                    <?php else: ?>
                        // Режим URL: Резервный вариант при сбое создания через API
                        discourseEmbedUrl: '<?php echo esc_url($permalink); ?>',
                    <?php endif; ?>
                    fullApp: true,
                    embedHeight: '800px',
                };

                (function() {
                    var container = document.getElementById('discourse-comments');

                    // Проверяет, поддерживает ли браузер IntersectionObserver
                    if ('IntersectionObserver' in window) {
                        var observer = new IntersectionObserver(function(entries, observer) {
                            entries.forEach(function(entry) {
                                if (entry.isIntersecting) {
                                    // Когда div появляется на экране, загружает скрипт
                                    loadDiscourse();
                                    observer.unobserve(entry.target);
                                }
                            });
                        }, { rootMargin: "1500px" }); // Загружает за 1500px до появления div

                        observer.observe(container);
                    } else {
                        // Резервный вариант для старых браузеров
                        loadDiscourse();
                    }

                    function loadDiscourse() {
                        var d = document.createElement('script'); 
                        d.type = 'text/javascript'; 
                        d.async = true;
                        d.src = window.DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
                        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
                    }
                })();
            </script>

Здесь вы можете увидеть снижение количества запросов после внедрения ленивой загрузки (и некоторые части сайта всё ещё кэшировались, так что это не окончательный результат):

  • Сокращение полезной нагрузки: Можем ли мы уменьшить ресурсы, загружаемые внутри встраиваемого элемента? Например, я заметил запросы к URL чата и проверкам кредитов ИИ — нужны ли они для встраиваемого представления?

  • Частота запросов: Реальные POST-запросы в реальном времени немного агрессивны. Может быть, мы можем снизить частоту опроса для встраиваемой версии?

  • Кэш: Улучшенное управление кэшем для встраиваемых тем для обработки пиков трафика.

2. Проблемы с аналитикой

В данный момент встраиваемый элемент запускает скрипты Google Analytics/GTM. Это удваивает количество просмотров наших страниц (один хит для поста, другой для iframe), что искажает наши данные. Было бы идеально, если бы система могла определить, что находится в iframe, и автоматически отключить любые скрипты отслеживания (включая аналитику Discourse).

3. Проблема с высотой iFrame

Это, вероятно, самое большое препятствие для UX. Если у поста нет комментариев, появляется странная пустая область. Если же ветка комментариев длинная, iframe обрезается после первых 2-3 комментариев, заставляя пользователя прокручивать содержимое внутри прокручиваемой области, что очень плохо, особенно на мобильных устройствах.

Чтобы действительно конкурировать с чем-то вроде Disqus, нам нужна динамическая высота (в зависимости от количества комментариев) и кнопка «Читать далее», которая раскрывает ветку после определённого количества ответов.

4. Конфликты плагинов

Поскольку встраиваемый элемент загружает все активные плагины, мы наблюдаем некоторое странное поведение. Например, «Google One Tap» появляется внутри поста блога. Когда пользователь входит в систему, iframe обновляется и перенаправляет его на домашнюю страницу сообщества вместо ветки комментариев. Возможность вручную отключать определённые плагины для встраиваемого представления была бы спасением.

5. Трение при входе в систему

Текущий процесс немного убивает конверсию: пользователь нажимает вход —> открывается новая вкладка —> происходит вход —> пользователь остаётся на домашней странице сообщества. Назад в посте блога iframe по-прежнему выглядит как неавторизованный, пока пользователь вручную не обновит всю страницу. Это запутанный цикл, из-за которого люди сдаются и уходят, прежде чем оставить комментарий.

После активации нового встраиваемого элемента наши ежедневные регистрации более чем удвоились, что здорово. Однако наши метрики вовлечённости не изменились. На самом деле, наши DAU/MAU упали — у нас больше пользователей, вошедших в систему, но они не взаимодействуют. Метрики вроде «Ежедневные вовлечённые пользователи», «Новые участники» и «Публикации» не показали никакого роста.

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

6. Мобильный интерфейс

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


Я действительно хочу сделать эту систему системой по умолчанию для Tecnoblog (и также для другого сайта, которым мы владеем). Дайте мне знать, если вы хотите глубже погрузиться в любой из этих пунктов!

14 лайков

Это будет исправлено в

11 лайков

Спасибо за подробный отзыв, @Thiago_Mobilon!

Я просмотрю список и постараюсь в конечном итоге охватить всё.

Я только что проверил, и похоже, что CSS на вашем сайте Discourse настроен неправильно. У вас дублируются заголовки cache-control, и один из них — no-cache.

curl -v https://tecnoblog.net/comunidade/stylesheets/common_cd45efa28175431b0b8ff143783178d55206920b.css?__ws=tecnoblog.net -s 2>&1 | grep cache-control
< cache-control: max-age=31556952, public, immutable
< cache-control: no-store, no-cache, must-revalidate, private
9 лайков

Вы используете встроенную интеграцию Google Analytics в Discourse?

8 лайков

Обработка этих запросов осуществляется в

9 лайков

Обработано в

11 лайков

Полагаю, Cloudflare добавил этот заголовок, потому что я отключил кэширование для директории /comunidade/. Если я его не удалю, будут применяться правила кэширования Cloudflare к CSS и JS Discourse, что потенциально может вызвать конфликты в будущем.

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

5 лайков

Я использую интеграцию Discourse с Google Tag Manager.

4 лайка

Они влияют на производительность для конечного пользователя, поскольку на каждой статье выполняется 59 запросов на загрузку 1,43 МБ CSS (сжатых до 340 КБ).

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

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

4 лайка

Отличная идея, я добавляю нативную поддержку этой функции.

11 лайков

Это более общая проблема, связанная с написанием сообщений на ходу, и она будет решена благодаря улучшениям, обсуждаемым в Creating/Editing a post on mobile: let's discuss the 2026 Discourse experience.

8 лайков

У нас есть отличный кэш для анонимных пользователей, заходящих на страницы тем, и он также покрывает этот новый режим, поэтому вы сможете хорошо масштабироваться для обработки всплесков, пока у вас достаточно воркеров Pitchfork и воркеров ввода-вывода Redis.

5 лайков

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

5 лайков

Добавил соответствующие метки в

8 лайков

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

        <h4 class="comments-main-title component-title">Комментарии</h4>
        <div id='discourse-comments'></div>

        <meta name='discourse-username' content='<?php echo esc_attr($discourse_author); ?>'>

        <script type="text/javascript">
            DiscourseEmbed = {
                discourseUrl: '<?php echo esc_url($discourse_url); ?>',
                
                <?php if ($use_topic_id): ?>
                    // Режим ID: Тема сохранена в базе данных, не подвержена изменениям URL
                    topicId: <?php echo intval($topic_id); ?>,
                <?php else: ?>
                    // Режим URL: Резервный вариант при сбое создания через API
                    discourseEmbedUrl: '<?php echo esc_url($permalink); ?>',
                <?php endif; ?>
                fullApp: true,
                lazyLoad: true, // отключить ленивую загрузку iframe
                lazyLoadMargin: '1500', // пиксели до видимой области для начала загрузки
                dynamicHeight: true,
                embedMinHeight: '400',
                embedMaxHeight: '3000',
					  embedHeight: '800px',
                // className: 'CLASS_NAME',
            };

            (function() {
            var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
            d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
            (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
            })();
        </script>
4 лайка

Можно ли здесь использовать <iframe loading="lazy">? Таким образом, нам не нужны будут кастомный JS или intersection observers?

4 лайка

О, это уже широко поддерживается в браузерах? Узнал что-то новое! Как можно скорее внесу изменения.

8 лайков

Спасибо за тестирование, нашли проблему

5 лайков

Отлично! Динамическая высота теперь работает как ожидается. Однако это привело к небольшой проблеме: когда я нажимаю для ответа, поле ввода для ответа пытается отрегулировать высоту iframe. В данном случае оно ошибочно стало 7385px в высоту.

Пост содержал 31 комментарий, а встроенный iframe был высотой 9757px (я установил embedMaxHeight на 15000px).

Обновление: Я заметил, что форма комментария расширяет высоту iframe до максимума, поэтому, когда я нажимаю «отменить», в макете остается большое пустое пространство под комментариями.

Screenshot 2026-04-16 at 16.03.37

5 лайков

Думаю, вам стоит задать более разумное значение для max-height в этом месте, например, от 1000 до 1500px.

Таким образом, эта функция решит вашу изначальную проблему:

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

Эта функция не уберёт «прокрутку внутри прокрутки» в ближайшее время.

Что касается мобильного редактора, я изучаю, что мы можем здесь сделать.

6 лайков