Tecnoblog の Discourse コメントに関する体験

こんにちは!

この新機能について、本当に興奮しています。このようなソリューションをずっと待っていたのですが、Tecnoblogの読者からの最初のフィードバックも素晴らしいものでした。コミュニティが統合されていることを非常に喜んでいます。

しかし、実際のテストを経て、これを本当にネイティブなコメントシステムのように感じさせ、さらに重要なのは、高トラフィックのサイトでも持続可能にするために克服すべきいくつかの技術的な課題を発見しました。

以下は、これまでの発見です:

1. パフォーマンスとサーバー負荷

フルアプリを埋め込んだ後、サーバー負荷が大幅に増加しました。Cloudflareを確認すると、リクエスト数が10倍に増えました。これを最適化するためのいくつかのアイデアがあります:

  • Lazy Loading: JSのlazy loadを実装すると、かなり改善します(すでにこれを回避するためのワークアラウンドを使用しています)。
            <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>

ここでは、Lazy Loadが実装された後のリクエスト数の減少を確認できます(また、ウェブサイトの一部はまだキャッシュされていたため、これは最終結果ではありません):

  • ペイロードの削減: 埋め込み内で読み込まれるリソースを減らすことは可能ですか?例えば、チャットURLやAIクレジットチェックのクエリに気づきましたが、これらは埋め込みビューに必要ですか?

  • リクエスト頻度: リアルタイムのPOSTリクエストは少し過激です。埋め込み版のポーリング頻度を少し下げることはできますか?

  • キャッシュ: トラフィックの急増に対応するための埋め込みトピックのキャッシュ管理を改善します。

2. アナリティクスの問題

現在、埋め込みはGoogle Analytics/GTMスクリプトを発火しています。これにより、ページビューが2倍になります(投稿用とiframe用でそれぞれ1回ずつ)。これはデータを混乱させます。システムがiframe内であることを検出し、自動的にすべてのトラッキングスクリプト(Discourseのアナリティクスも含む)を停止することが理想的です。

3. iFrameの高さの問題

これはおそらくUXにおける最大の課題です。コメントがない投稿の場合、奇妙な空白スペースができてしまいます。長いスレッドがある場合、iframeは最初の2〜3つのコメントで切り捨てられ、「スクロールの中のスクロール」を強制します。これはモバイルデバイスでは特に問題です。

Disqusのようなものと競争するためには、高さを動的に(コメントの数に応じて)し、一定数の返信後にスレッドを展開する「もっと読む」ボタンが必要です。

4. プラグインの競合

埋め込みがすべてのアクティブなプラグインを読み込むため、いくつかの奇妙な挙動が見られます。例えば、「Google One Tap」がブログ投稿内に表示されます。ユーザーがログインすると、iframeが更新され、コミュニティのホーム画面に飛ばされます。埋め込みビューで特定のプラグインを手動で無効にできることは、本当に助かります。

5. ログインの摩擦

現在のフローは少しコンバージョンを妨げています:ユーザーがログインをクリック → 新しいタブが開く → ログインが行われる → ユーザーはコミュニティのホーム画面に残る。ブログ投稿に戻ると、iframeはまだログアウト状態のままです。ユーザーが手動でページ全体を更新するまで、ログイン状態にはなりません。これは混乱を招くループで、コメントする前にユーザーが諦めて去ってしまいます。

新しい埋め込みを有効にして以来、毎日の登録数が2倍以上に増加しました。これは素晴らしいことです。しかし、エンゲージメント指標は全く動きませんでした。実際、DAU/MAUは低下しました。ログインしたユーザーは増えたものの、彼らは相互作用していません。「毎日アクティブなユーザー」、「新しい貢献者」、「投稿数」などの指標は増加していません。

これは、人々が会話に参加したいと思っているが、ログインループで迷子になり、実際にコメントする前に投稿を放棄していることを証明しています。

6. モバイルUI

モバイルでは、返信ウィンドウが画面全体を占めるため、返信している会話の文脈が失われます。少し窮屈な感じがあります。これをよりコンパクトに保つための対策があれば、大きな勝利になります。


Tecnoblog(および所有する別のサイト)でこれがデフォルトのシステムになるようにしたいです。これらのポイントのいずれかについてさらに深く掘り下げたい場合は、お知らせください!

「いいね!」 14

これは

によって修正されます

「いいね!」 11

詳細なフィードバックをありがとうございます @Thiago_Mobilon

リストを確認して、最終的にはすべてをカバーするように努めます。

先ほど確認したところ、Discourse サイトの CSS が誤って設定されているようです。cache-control ヘッダーが重複しており、そのうちの1つが 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

Discourseの標準的なGoogle Analytics統合機能を使用していますか?

「いいね!」 8

これらについては、以下のプルリクエストで対応しています。

「いいね!」 9

対応済み。

「いいね!」 11

Cloudflare がそのヘッダーを追加したのだと思います。/comunidade/ ディレクトリに対してキャッシュをバイパスする設定をしていたからです。これを削除しないと、Cloudflare が Discourse の CSS や JS にキャッシュルールを適用してしまい、後で競合が発生する可能性があります。

いずれにせよ、キャッシュの問題を取り上げたのは、サーバーの負荷を減らすためでした。CSS ファイルは静的ファイルですよね?もしそうなら、キャッシュされないことは望ましくないものの、サーバーの負荷に直接影響を与えるものではありません。

「いいね!」 5

私はDiscourseのGoogle Tag Managerとの連携機能を利用しています。

「いいね!」 4

各記事で 1.43MB の CSS(圧縮すると 340KB)を 59 リクエストでダウンロードしているので、エンドユーザーのパフォーマンスに影響します。

また、キャッシュが破損しないことをサイト側に期待しているため、通常はこのルートはほとんど使用されません。そのため、これらは Ruby サーバーによって提供されています。

間違っていなければ、キャッシュが破損した状態でこれらを提供すると、データベースにまでアクセスすることになります。

「いいね!」 4

素晴らしいアイデアですね。ネイティブサポートを追加しています。

「いいね!」 11

これはモバイルで投稿を作成する際の一般的な問題であり、Creating/Editing a post on mobile: let's discuss the 2026 Discourse experience の改善により解決されるでしょう。

「いいね!」 8

匿名ユーザーがトピックページにアクセスする際の素晴らしいキャッシュがあり、この新しいモードもカバーしているので、十分な数のPitchforkワーカーとRedis I/Oワーカーがあれば、急増にも問題なくスケールできるはずです。

「いいね!」 5

バックグラウンドのタブや高負荷イベント時には、ポーリングは自動的に頻度が下がるようになっています。これについても同様の対応が必要です。

「いいね!」 5

これらにタグを付けるようにしました

「いいね!」 8

動的高さを正しく機能させるのに苦労しています。Discourseを更新し、スニペットを最新の設定で更新しましたが、問題は依然として続いています。

        <h4 class="comments-main-title component-title">Comentários</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モード: DBに保存されたトピック、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 Observerを必要としませんよね?

「いいね!」 4

ああ、今ではブラウザで広くサポートされているんですか? 知りませんでした!できるだけ早く修正します。

「いいね!」 8

テストありがとうございます。問題を発見しました

「いいね!」 5

素晴らしい!動的な高さが期待通りに動作するようになりました。ただし、これにより小さな問題が発生しました:返信をクリックすると、返信の入力フィールドがiframeの高さに合わせて調整しようとするのです。この場合、誤って7385pxの高さになってしまいました。

投稿には31件のコメントが含まれており、埋め込まれたiframeの高さは9757pxでした(embedMaxHeightを15000pxに設定していました)。

更新:実際、コメントフォームがiframeの高さを最大値まで拡大していることに気づきました。そのため、「破棄」をクリックすると、コメントの下に大きな空白スペースが残った状態になります。

Screenshot 2026-04-16 at 16.03.37

「いいね!」 5

max-height の値をもう少し現実的な値、例えば 1000px〜1500px 程度に設定する必要があると思います。

これにより、以下のような初期の問題

が解決され、一定の範囲まで拡大可能になりますが、Discourse 標準の無限スクロールの動作を考えると、高さをこれ以上大きくする必要はないでしょう。

この機能では、近い将来「スクロール内のスクロール」を解消することはできません。

モバイル版の投稿エディタについては、どのような対応が可能か検討しています。

「いいね!」 6