Tecnoblog 使用 Discourse 评论系统的体验

你好!

我对这个新功能感到非常兴奋。我期待这样的解决方案已经很久了,我们 Tecnoblog 读者的初步反馈也非常好——他们很喜欢社区集成带来的体验。

不过,经过一些实际测试后,我发现了一些技术障碍,需要克服这些问题,才能让这个系统真正像一个原生的评论系统,更重要的是,使其能够适应高流量网站的需求。

以下是我目前发现的一些问题:

1. 性能与服务器负载

在嵌入完整应用后,我们的服务器负载显著上升。查看 Cloudflare 数据,我们的请求量增加了 10 倍。以下是一些优化建议:

  • 懒加载:对 JavaScript 实施懒加载非常有帮助(我已经采用了一种变通方案)。
            <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" }); // 在 div 进入视口前 1500px 开始加载

                        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 和 AI 信用检查的查询——这些在嵌入视图中是否必要?

  • 请求频率:实时 POST 请求略显激进。我们是否可以降低嵌入版本的轮询频率?

  • 缓存:改进嵌入话题的缓存管理,以应对流量高峰。

2. 分析数据混乱

目前,嵌入内容会触发 Google Analytics/GTM 脚本。这导致我们的页面浏览量翻倍(一次是文章本身,另一次是 iframe),从而扰乱了我们的数据。理想情况下,系统应能检测到它运行在 iframe 中,并自动禁用所有跟踪脚本(包括 Discourse 自身的分析脚本)。

3. iframe 高度问题

这可能是用户体验方面最大的障碍。如果文章没有评论,会出现奇怪的空白间隙;如果评论线程较长,iframe 会在前 2 或 3 条评论处被截断,迫使出现“滚动中的滚动”,这在移动端尤其糟糕。

要想真正与 Disqus 等系统竞争,我们需要高度能够动态调整(根据评论数量),并在一定数量的回复后提供一个“阅读更多”按钮来展开整个线程。

4. 插件冲突

由于嵌入内容会加载所有激活的插件,我们观察到一些异常行为。例如,“Google One Tap”会弹出在博客文章内部。当用户登录后,iframe 会刷新,并将用户导向社区主页,而不是评论线程。能够手动禁用嵌入视图中的特定插件将是一个巨大的帮助。

5. 登录摩擦

当前的流程有些阻碍转化:用户点击登录 → 打开新标签页 → 完成登录 → 用户停留在社区主页。回到博客文章时,iframe 仍显示为未登录状态,直到用户手动刷新整个页面。这种令人困惑的循环让用户在能够评论之前就放弃并离开。

自从启用新的嵌入功能后,我们的每日注册量翻了一倍以上,这非常好。然而,我们的参与度指标却没有任何变化。事实上,我们的DAU/MAU 比率下降了——我们拥有更多已登录用户,但他们并未进行互动。“每日活跃用户”、“新贡献者”和“发帖数”等指标均未出现增长。

这证明人们希望参与对话,但他们被困在登录循环中,在能够实际评论之前就放弃了文章。

6. 移动端 UI

在移动端,回复窗口会占据整个屏幕,导致你完全失去对正在回复的对话上下文的感知。这让人感觉有些压抑——如果我们能让它更紧凑,将是一个巨大的进步。


我真的很希望将这套系统作为 Tecnoblog(以及我们拥有的另一个网站)的默认评论系统。如果您想深入了解其中任何一点,请随时告诉我!

9 个赞

这将通过以下链接修复:

7 个赞

感谢详细的反馈 @Thiago_Mobilon

我会处理这份清单,并努力最终涵盖所有内容。

我刚刚在这里检查了一下,看起来您的 Discourse 站点上的 CSS 配置有误。您有两条 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
6 个赞

您是否使用了 Discourse 内置的 Google Analytics 集成?

5 个赞

在以下链接中处理这些问题:

6 个赞

已在以下链接中处理:

8 个赞

我认为 Cloudflare 必定是添加了该响应头,因为我绕过了 /comunidade/ 目录的缓存。如果我不移除它,它会将缓存规则应用于 Discourse 的 CSS 和 JS 文件,这可能会在将来产生冲突。

无论如何,我提出缓存问题时,主要目的是减轻服务器负载。CSS 文件是静态的,对吗?如果是这样,那么它们未被缓存虽然不理想,但不会直接影响服务器负载。

2 个赞

我正在使用 Discourse 与 Google Tag Manager 的集成。

1 个赞

它们会影响最终用户的性能,因为每篇文章都会发起 59 次请求,下载 1.43MB 的 CSS(压缩后为 340KB)。

此外,这些文件也是由 Ruby 服务器提供的,因为我们期望网站不会破坏缓存,这意味着在正常情况下,该路由极少被使用。

如果我没记错的话,当缓存被破坏时,提供这些文件甚至会导致数据库查询。

1 个赞

这是个好主意,我正在添加对此的原生支持

7 个赞

这是一个更普遍的移动设备撰写问题,并将受益于以下讨论中的改进:Creating/Editing a post on mobile: let's discuss the 2026 Discourse experience

5 个赞

我们为访问主题页面的匿名用户提供了一个出色的缓存系统,该系统也支持这种新模式。因此,只要拥有足够的 Pitchfork 工作进程和 Redis I/O 工作进程,您应该能够很好地扩展以应对流量高峰。

2 个赞

轮询机制在后台标签页或高负载事件期间会自动降低频率,此处也应适用同样的规则。

2 个赞

已同意为此添加标签

5 个赞

我在让动态高度正常工作方面遇到了困难。尽管已更新 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>

https://tecnoblog.net/noticias/samsung-wallet-agora-suporta-pix-por-aproximacao/

1 个赞

我们能否在这里使用 <iframe loading="lazy">?这样我们就不需要自定义 JS 或交集观察器(Intersection Observers)了?

1 个赞

哦,现在各大浏览器都已广泛支持了吗?涨知识了!我会尽快修改。

5 个赞

感谢测试,已找到问题

3 个赞

太好了!动态高度现在按预期运行了。不过,这引入了一个小问题:当我点击回复时,回复输入框会尝试根据 iframe 的高度进行调整。在这种情况下,它错误地变成了 7385px 高。

该帖子包含 31 条评论,嵌入的 iframe 高度为 9757px(我将 embedMaxHeight 设置为 15000px)。

https://tecnoblog.net/noticias/samsung-wallet-agora-suporta-pix-por-aproximacao/

更新:我注意到评论表单会将 iframe 的高度扩展到其最大值,因此当我点击“放弃”时,布局会在评论下方留下大片空白区域。

Screenshot 2026-04-16 at 16.03.37

2 个赞

我认为你需要在那里将 max-height 设置为一个更合理的值,比如 1000 到 1500 像素。

因此,该功能将解决你最初遇到的问题:

并且可以扩展到一定程度,但鉴于 Discourse 原生的无限滚动行为,你不希望高度增加得太多。

该功能短期内不会消除“滚动中的滚动”问题。

至于移动端编辑器,我正在研究我们可以采取哪些措施。

3 个赞