In letzter Zeit habe ich mich mit der Optimierung der Leistung durch Lazy-Loading beschäftigt. Kürzlich habe ich darüber geschrieben, wie man Google Maps per Lazy-Loading lädt und wie man responsive Google AdSense-Anzeigen per Lazy-Loading lädt. Nun ist es Zeit für Disqus, einen Dienst zum Einbetten von Kommentaren auf Ihrer Website. Es ist ein großartiger Dienst. Er erspart die Kopfzerbrechen bei der Entwicklung eines eigenen lokalen Kommentarsystems, der Bekämpfung von Spam usw. Kürzlich habe ich an der Implementierung des Widgets in einem meiner Projekte gearbeitet.
Das Problem
Layout-bedingt spielen Kommentare meist eine untergeordnete Rolle. In vielen Fällen werden Kommentare von den Besuchern gar nicht gesehen, da sie nicht nach unten scrollen, bis sie dort sind. Aber wissen Sie was? Standardmäßig werden sie auf der Website geladen, egal was passiert. Der verschwendete Bandbreitenverbrauch ist ein Problem.
Werfen wir einen Blick auf die technische Implementierung, die von Disqus offiziell empfohlen wird
<div id="disqus_thread"></div>
<script>
(function() {
var d = document, s = d.createElement('script');
s.src = '//username.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
Hier sagen sie: *"Platzieren Sie den folgenden Code dort, wo Disqus geladen werden soll."* Nehmen wir an, Sie sind ein guter Entwickler und fügen normalerweise alle <script src="..."></script>-Fragmente direkt vor dem schließenden Tag </body> ein. Dann beschließen Sie eines schönen Tages, Disqus-Kommentare auf Ihrer Website zu implementieren und platzieren den obigen Code irgendwo in der Mitte des Dokuments, wo der Kommentarbereich vorgesehen war.
Was passiert? Die allererste herunterzuladende JavaScript-Datei ist username.disqus.com/embed.js. Das bedeutet nicht unbedingt, dass sie zuerst heruntergeladen wird, aber sie ist die erste in der Reihe der JavaScript-Dateien, die die Aufmerksamkeit des Browsers erregt. Sollte der erste Platz nicht für die Haupt-JavaScript-Datei Ihrer Website reserviert sein? Es gibt viele Dinge (wie "schlafende" <button>s usw.), die schiefgehen können, wenn Ihre Haupt-JavaScript-Datei spät geladen wird, besonders wenn Sie damals bei der Entwicklung dieser Website nicht die Prinzipien der *graceful degradation* (dezenten Degradation) oder *progressive enhancement* (progressiven Verbesserung) befolgt haben.
Dies stört auch andere externe Ressourcen auf Ihrer Website, wie Bilder und CSS-Dateien. Stellen Sie sich vor, Sie nutzen ein Smartphone unter 2G-Netzwerkbedingungen und warten darauf, dass das Kommentar-Widget geladen wird, nur weil Sie wegen eines Katzenfotos gekommen sind.
Ich habe einen Test gemacht. Es stellt sich heraus, dass das Disqus-Widget mit null Kommentaren 2,49 MB wiegt! Eine Menge Netzwerkanfragen für JavaScript-, CSS-, Bild- und Schriftdateien, die in vielen Fällen die anderen, vielleicht kritischen Teile oder Funktionen Ihrer Website unnötig verlangsamen.

Die Lösung: Kleines JavaScript-Plugin
Um Disqus per Lazy-Loading laden zu können, habe ich ein kleines JavaScript-Plugin entwickelt, das die Arbeit erledigt. Egal wo sich die Kommentarzone befindet, oberhalb oder unterhalb des Viewports, sie wird nicht geladen, wenn es keinen Grund dafür gibt.

Das Plugin selbst ist ein winziges Stück JavaScript. Ich habe zwei Versionen davon erstellt: Vanilla und jQuery. Ich habe es disqusLoader genannt. Sie können die Dateien hier herunterladen
- disqusloader.js; keine Abhängigkeiten (IE 9+).
779 Bytes, wenn minifiziert und komprimiert. - jquery.disqusloader.js; jQuery-Abhängigkeit.
569 Bytes, wenn minifiziert und komprimiert.
So richten Sie es ein. Zuerst müssen Sie ein Element in HTML einfügen, an dem Sie den Kommentarbereich haben möchten.
<div class="disqus"></div>
Initialisieren Sie dann das Plugin wie folgt
// vanilla
disqusLoader( '.disqus', { scriptUrl: '//username.disqus.com/embed.js' });
// jQuery
$.disqusLoader( '.disqus', { scriptUrl: '//username.disqus.com/embed.js' });
"Das ist großartig, aber was ist mit der spezifischen Disqus-Konfiguration?", könnten Sie fragen. Sicher, es gibt ein weiteres Argument, das einen Disqus-nativen Wert akzeptiert. Es gibt auch ein paar weitere Plugin-spezifische Optionen
var options =
{
scriptUrl: '//username.disqus.com/embed.js',
/*
@type: string (url)
@default: none
@required
URL of Disqus' executive JS file. The value is memorized on the first function call
and ignored otherwise because Disqus allows only one instance per page at the time.
*/
laziness: 1,
/*
@type: int (>=0)
@default: 1
Sets the laziness of loading the widget: (viewport height) * laziness . For example:
0 - widget load starts when at the least a tiny part of it gets in the viewport;
1 - widget load starts when the distance between the widget zone and the viewport is no more than the height of the viewport;
2 - 2x viewports, etc.
*/
throttle: 250,
/*
@type: int (milliseconds)
@default: 250
Defines how often the plugin should make calculations during the
processes such as resize of a browser's window or viewport scroll.
250 = 4 times in a second.
*/
/*
@type: function
@default: none
Disqus-native options. Check Disqus' manual for more information.
*/
disqusConfig: function()
{
this.page.title = 'Page Title';
this.page.url = 'http://url.to/your-website';
this.page.identifier = 'unique-identifier';
}
};
// vanilla
disqusLoader( '.disqus', options );
// jQuery
$.disqusLoader( '.disqus', options );
Probieren Sie es selbst aus
Sie können auch zum Projekt auf GitHub beitragen oder es verfolgen.
Disqus Callbacks
Callbacks sind großartig, weil Sie auf Benutzeraktionen reagieren können. Es gibt nur eine Art von Callback, die von Disqus offiziell dokumentiert ist. Wenn man sich den Quellcode der `embed.js`-Datei ansieht, kann man weitere vordefinierte Callback-Typen erkennen.

Es scheint jedoch, dass nur zwei davon aktiviert sind: onNewComment und onReady. Das reicht für eine kleine, aber spürbare Verbesserung: eine Ladeanzeige.
Ergänzende Ladeanzeige
Das Laden des Disqus-Widgets besteht normalerweise aus zwei Teilen
- Laden der `embed.js`-Datei
- Laden der inneren Assets und Ausführen anderer Arten von Netzwerkanfragen
Disqus selbst kümmert sich um den 2. Schritt, den sie mit dem animierten Bild kennzeichnen. Aber was ist mit dem 1. Schritt? Es gibt viele Gründe, warum das Laden externer JavaScript-Dateien zehn Sekunden oder mehr dauern kann. Der Clou ist, dass dem Benutzer, unabhängig von den Netzwerkbedingungen, immer noch mitgeteilt wird, dass eine Kommentarfunktion auf Ihrer Website verfügbar ist. Benutzererlebnis steckt im Detail!

Der technische Ansatz ist einfach: ein neues HTML-Element und eine JavaScript-Callback-Funktion, die hilft, das Element auszublenden.
<div class="disqus-placeholder">Loading comments...</div>
<div class="disqus"></div>
// vanilla
disqusConfig: function()
{
this.callbacks.onReady = [function()
{
var el = document.querySelector( '.disqus-placeholder' );
if( el.classList )
el.classList.add( 'is-hidden' ); // IE 10+
else
el.className += ' ' + 'is-hidden'; // IE 8-9
}];
}
// jQuery
disqusConfig: function()
{
this.callbacks.onReady = [function()
{
$( '.disqus-placeholder' ).addClass( 'is-hidden' );
}];
}
.disqus-placeholder.is-hidden { display: none; }
Sie können dies in Aktion auf der Demoseite sehen. Aber zuerst leeren Sie den Browser-Cache und drosseln die Netzwerkgeschwindigkeit.
Mehrere Instanzen oder Websites gleichzeitig?
Bei der Arbeit an der Technik habe ich ein paar wichtige Einschränkungen entdeckt, die heute bestehen…
Es ist unmöglich, mehrere Skriptquellen auf einer einzigen Seite zu haben
Sobald die Skriptdatei (z.B. //username.disqus.com/embed.js) geladen ist, wird die globale Variable window.DISQUS erstellt, aber nur, wenn sie nicht bereits zuvor gesetzt wurde (was ein schlechtes Zeichen ist, aber graben wir tiefer). Ich habe also einen Test gemacht. Ich habe das Widget aus dem Quellskript A initialisiert. Dann habe ich etwas Platz für die zukünftige Variable window.DISQUS = undefined geschaffen und das Widget der Quelle B initialisiert. Das Ergebnis war jedoch ein Durcheinander: Callback-Funktionen wurden mehrmals ausgelöst, die Kommentare wurden dupliziert usw. Offensichtlich ist der aktuelle Code von Disqus nicht darauf ausgelegt, mehrere Variablen zu unterstützen und individuell mit jeder Widget-Instanz zu operieren.
Es ist unmöglich, mehrere Widgets gleichzeitig auf einer einzigen Seite zu haben
Es gibt eine öffentliche JavaScript-Methode reset() verfügbar im Objekt DISQUS. Wenn Sie technische Erfahrung mit Disqus haben, wissen Sie vielleicht, dass das Widget in ein Element eingefügt wird, das für die id den Wert disqus_thread hat. Ich habe einen Test mit zwei Elementen gemacht: Das Widget im ersten Element geladen, das ID-Attribut entfernt und es an das zweite Element angehängt. Schließlich habe ich die Reset-Funktion aufgerufen und erwartet, dass die zweite Instanz neben der ersten erscheint. Das Aufrufen der Funktion zum Laden einer neuen Instanz *zerstört* jedoch auch alle zuvor initialisierten Widgets. Leider ist Disqus heute nur für eine einzige Instanz zur gleichen Zeit konzipiert.
Es ist möglich, das Widget in Echtzeit neu zu laden
Es gibt eine gute Nachricht! Auch wenn es nicht möglich ist, mehrere Widget-Instanzen gleichzeitig zu haben, können Sie die alten immer noch zerstören und neue laden. Lassen Sie uns diese Theorie in die Praxis umsetzen, mit der wahrscheinlich typischsten Situation: Tabs. Alles, was Sie tun müssen, ist, das Plugin jedes Mal aufzurufen, wenn der neue Tab aktiviert wird.
<div class="tabcontent" data-disqus-id="venus" data-disqus-title="Venus"></div>
<div class="tabcontent" data-disqus-id="earth" data-disqus-title="Earth"></div>
<div class="tabcontent" data-disqus-id="mars" data-disqus-title="Mars"></div>
// call this function every time a tab is clicked:
var initDisqus = function( content )
{
disqusLoader( content,
{
scriptUrl: '//username.disqus.com/embed.js',
disqusConfig: function()
{
this.page.identifier = content.getAttribute( 'data-disqus-id' );
this.page.title = content.getAttribute( 'data-disqus-title' );
}
});
}
Sie können dies in Aktion sehen oder den vollständigen Code auf der Demoseite einsehen.
Abschließende Gedanken
Dieser Beitrag handelt nicht von den Fehlern in Disqus. Es geht um die Fehler, die wir Entwickler machen. Unsere Welt ist voller Werkzeuge und es liegt an uns, wie wir sie nutzen. Auch wenn diese Werkzeuge bestimmte Probleme lösen, bringen sie normalerweise einige andere mit sich, wenn wir nicht die gebotene Sorgfalt walten lassen, wenn wir sie implementieren. Jede Entscheidung, den einfachsten Weg zu gehen, führt zu verlorenen Nutzern, sinkenden Konversionen und erhöhten Absprungraten. Sie können bereits Disqus, Google AdSense, Google Maps, Social Media Buttons per Lazy-Loading laden, Sie können auch eigene Techniken entwickeln und teilen. Seien Sie verantwortungsbewusst!
Verdammt erstaunlich!!! Ich glaube, ein Kunde hat so etwas in seinem Disqus. Ehrlich gesagt, ich habe es nie als großes Problem betrachtet, da ich auch die Ladung von Disqus nicht getestet habe. Wir empfehlen eigentlich, Kommentare nur zu laden, wenn jemand es wünscht, sodass die Kosten für selbst gehostete oder externe Kommentare geringer sind und die Absicht vorhanden sein muss, aber dies ist eine wirklich überzeugende Alternative, die viele der gleichen Vorteile hat und Benutzern hilft, die vielleicht etwas Wunderbares sagen oder teilen, aber aus irgendeinem Grund nicht durchklicken.
Das ist eine großartige Idee, die mir irgendwie nie in den Sinn gekommen ist. Ähnlich wie Lewis Cowles sagte, habe ich nie über dieses Problem nachgedacht, bis ich diesen Beitrag sah. Als das Thema angesprochen wurde, begann ich, die Ladung zu testen, und in vielen Fällen ist sie größer als die Ressourcen der gesamten Seite zusammen.
Auch der Hinweis, dass Leute das Skript dort platzieren, wo sie Kommentare anzeigen möchten, anstatt im Footer zu priorisieren. . . ja, genau das habe ich getan.
Vielen Dank für dieses Projekt und dafür, dass Sie diesen Beitrag veröffentlicht haben. Ich lade viele Dinge per Lazy-Loading, aber aus irgendeinem Grund sind mir Kommentare nie in den Sinn gekommen, und jetzt habe ich etwas, das mir dabei hilft. Danke!
Ich sehe das nicht genauso wie Sie. Disqus nimmt auf meiner Website keine 2,49 MB ein (eher 250 KB).
Außerdem werden zwar einige Teile von Disqus geladen, wenn die Seite geladen wird, aber die Kommentare selbst werden nur dann per Lazy-Loading geladen, wenn sie im Viewport angezeigt werden. Zumindest ist das meine Erfahrung mit Chrome.
Ein Viertel MB... Denken Sie einfach darüber nach (unabhängig von der ursprünglich genannten Größe). 250 KB bei einer langsamen Verbindung oder 3G oder wackelhaftem 1-Balken-WLAN ist keine optimale Erfahrung. Würde nur das Laden bei Bedarf ihre Erfahrung definitiv verbessern, oder?
Vollkommen im Einklang mit TrueTheWeb.
Ich war tatsächlich erstaunt über die zitierte 2,49 MB in diesem Artikel und bin zu meiner Website gerannt, um das zu überprüfen.
Anscheinend ist das falsche Werbung. Der Artikel sollte die korrekte Belastung der Website angeben und den Lesern erlauben zu beurteilen, ob dies akzeptabel ist oder nicht.
Das ist einfach inakzeptabel.
Für einen typischen Benutzer lädt das Disqus-Skript etwa 814,32 KB Daten (Kommentarblock ohne Kommentare). Wenn Sie als Administrator im Disqus-System angemeldet sind, müssen mehr als 2 MB Daten heruntergeladen werden.
Hätte man die Magie vollbringen können?
Natürlich, aber besser, diese leichte Abhängigkeit hinzuzufügen... Hahaha
Das ist so cool
Sie prüfen den Viewport.
Aber die zweitwichtigste Sache ist die URL
z.B. wenn Sie einen Link zu einem Kommentar senden, sieht das typischerweise so aus:
URL#comment-2924759399.In diesem Fall, da nur Disqus geladen wird, scrollt die Seite zum Kommentar.
Diese Funktionalität fehlt in Ihrem Plugin, um zu prüfen, ob die URL auf einen Kommentar verweist.
window.location.hash ist Ihr Freund. Vielleicht braucht dieses Plugin einen Beitrag. Ich bin mir ziemlich sicher, dass Sie den Viewport-Test finden und nach Abschluss des Seitenaufrufs, wenn es einen Hash gibt, der dem Regex
/[#]comment[-]\d+/entspricht, das Plugin auslösen können. Es benötigt auch einen Callback, der zur geladenen Kommentarseite scrollt und einen Zustand hat, so dass Sie den Kommentar nur einmal erkennen, aber es ist kaum das Ende der Welt, nachdem der Autor so weit gekommen ist, dass Sie ein wenig Arbeit und Gedanken investieren...Habe gerade das Lazy-Loading-Skript zu unseren Disqus-Kommentaren hinzugefügt (Beispiel hier). Großartige Arbeit, insgesamt tut es, was es verspricht. Ein paar Beobachtungen für andere beim Hinzufügen des Skripts.
In Ihren Anweisungen erwähnten Sie, dass Sie einen DIV erstellen sollen. Sie sollten hinzufügen, dass das Skript dann dynamisch `id=disqus_thread` in diesen DIV injiziert. Ich habe meine eigene benutzerdefinierte ID zum DIV hinzugefügt, da ich wollte, dass es als Wrapper für den Disqus-Container dient und ihn dynamisch ein-/ausblendet, aber die Konsole gab immer wieder zurück, dass `document.getElementByID(...)` null ist. Es dauerte eine Weile, bis ich verstand, was los war.
Wenn der Stil des `.disqus`-DIVs anfänglich auf `display:none` gesetzt ist, lädt das Skript die Kommentare NICHT per Lazy-Loading, sondern lädt sie einfach, sobald die Seite geladen ist. Ich habe versucht, den Kommentar-Wrapper auf der Seite anfänglich auszublenden, musste aber aufgrund dieses Verhaltens eine Umgehungslösung finden.
Es scheint manchmal, dass die Kommentare geladen werden, bevor sich der Benutzer auch nur in der Nähe des Kommentarcontainers auf der Seite befindet. Auf dieser Seite zum Beispiel lädt das Scrollen zur Mitte die Kommentare per Lazy-Loading.
Danke für die gute Arbeit!
Hallo, hier von Disqus.
Zuerst einmal vielen Dank, dass Sie Disqus nutzen und Zeit darauf verwenden, die Entwicklererfahrung zu verbessern. Als ich Ihren Artikel las, erkannte ich, dass es einige Punkte gibt, die eine Klarstellung von einer Quelle erster Hand gebrauchen könnten, also hier sind sie :)
Das ist größtenteils nicht der Fall, da alle Assets und Skripte, die Disqus verwendet, sehr stark gecacht werden, so dass Sie nicht wirklich viel Bandbreite verschwenden, wenn überhaupt.
Völlig irreführend. Erstens fügt der Browser das Skript am Ende seiner Prioritätenliste hinzu, da Skriptelemente, die aus Skripten erstellt werden, asynchron geladen werden. Deshalb haben wir den Inline-Skript-Ansatz verwendet. Heutzutage können wir mit modernen Browsern einfach das Attribut
asynchinzufügen, um die gleichen Vorteile zu erzielen, zusätzlich zum Vorwärtsscannen des Browsers, sodass er die Datei sogar noch früher erkennt (aber sie aufgrund des async-Attributs immer noch in eine niedrigpriorisierte Warteschlange einordnet). Sie können mehr in diesem ausgezeichneten Artikel von Ilya Grigorik lesen: https://www.igvita.com/2014/05/20/script-injected-async-scripts-considered-harmful/Dies ist wieder völlig falsch. Was Sie wahrscheinlich sehen, ist das Vorladen unserer erweiterten Community-Funktionen, die erst nach allem auf der Seite (einschließlich des gesamten Disqus-Kommentar-Widgets) vorab geladen werden. Dies geschieht auch nur auf Desktop-Browsern, sowohl um die Bandbreite auf mobilen Geräten zu sparen als auch einfach, weil wir auf mobilen Geräten keine Sidebar anzeigen können. Die Kern-Größe beträgt etwa 220 KB für eine Seite voller Kommentare. Dies beinhaltet embed.js, den Lade-Spinner und fast alles andere. Außerdem ist dies stark gecacht, so dass Sie diesen Preis nur einmal zahlen. Alle nachfolgenden Ladevorgänge, auch auf verschiedenen Seiten, sind erheblich günstiger, da Sie fast alles in Ihrem Cache haben.
Ich möchte auch hinzufügen, dass wir zur weiteren Optimierung aller Dinge tatsächlich das Laden aller Bilder (einschließlich Benutzeravataren), Rich-Media-Inhalte wie YouTube-Einbettungen usw. verzögern, es sei denn, Sie scrollen weiter nach unten, sodass wir denken, dass Sie sie wahrscheinlich sehen werden. Wir machen etwas Ähnliches für die Code-Hervorhebungsfunktion: Solange wir nicht wissen, dass es Code gibt, der in einem Kommentar hervorgehoben werden soll, laden wir diese Bibliothek einfach nicht, damit Sie die Kosten nicht tragen.
Sie können immer einen String in Ihrem `#disqus_thread`-Div einfügen, der etwas wie "Disqus comments" sagt, das automatisch durch den tatsächlichen Inhalt ersetzt wird. Wir hatten früher einen Text, der "Comments powered by Disqus" sagte, wobei Disqus ein Link war, aber dann dachten Leute, wir würden Backlinks für Google wollen, also haben wir ihn entfernt (und nein, wir haben keine Backlinks für Google-Rankings angestrebt, wir haben nur das Attribut
rel=nofollowvermisst).Nicht wirklich. Das Setzen von
window.DISQUSaufnulllässt den bestehenden und bereits ausgeführten Code nicht verschwinden. Es macht es nur sehr schwierig oder unmöglich, ihn zu erreichen. Deshalb überschreiben wir Dinge absichtlich nicht, wenn wir feststellen, dass Sie Disqus bereits auf einer Seite geladen haben. Das spart Ihrer Seite, nicht uns :)Es ist wirklich nicht notwendig, die ID vom vorherigen Element zu entfernen und sie dann einem neuen zu geben. Es gibt eine nicht offiziell unterstützte (aber jetzt funktionierende und schon seit einiger Zeit funktionierende)
disqus_container_id, mit der Sie die ID des Containers festlegen können, in dem Disqus geladen werden soll. Nochmals, nicht offiziell unterstützt, also wenn es eines Tages aufhört zu funktionieren, sind Sie gewarnt :)Das ist absichtlich, um Lecks zu vermeiden, da
DISQUS.reset, wie der Name schon sagt, dazu gedacht war, das Widget zurückzusetzen, nicht ein neues zu starten. Es gibt ein paar Teile im Code, die davon ausgehen, dass es das einzige aktive Disqus-Widget auf der Seite sein wird, aber die Gesamtarchitektur erlaubt tatsächlich viele Widgets. Es sind hauptsächlich die Usability-Bits, um die wir uns Sorgen machten, also haben wir diesen Weg geschlossen. Interessant wäre jedoch zu erfahren, warum Sie gleichzeitig mehrere Widgets auf einer Seite laden möchten.Ja, und das wurde bereits öffentlich dokumentiert, wie Sie vorgeschlagen haben, wo wir Leuten von
DISQUS.reseterzählen. Die Gefahr dabei ist, dass es sehr einfach ist, Ihre Threads zu beschädigen, indem Sie mehrere Bezeichner für dieselbe URL verwenden, wie Sie es getan haben. Ihre Kommentar-Threads werden dann getrennt und sind damit schwer wiederherzustellen. Sehen Sie hier weitere Informationen: https://help.disqus.com/customer/en/portal/articles/2158629-use-configuration-variables-to-avoid-split-threads-and-missing-commentsUnternehmen wie Disqus existieren, damit Sie sich um eine Sache weniger sorgen müssen. Wir sind ein engagiertes und sehr erfahrenes Team von Ingenieuren und anderen Leuten, denen die Ladeleistung am Herzen liegt, die gut mit den Seiten zusammenarbeiten, auf denen wir eingebettet sind, den kleinstmöglichen Fußabdruck mit großartigem Caching und einer großartigen Benutzererfahrung haben. Wir sind nicht perfekt, ja, aber zumindest sind wir ein engagiertes Team, um diesen Teil Ihrer Seite und Ihrer Erfahrung großartig zu machen, damit Sie sich nicht darum kümmern müssen. Sie können darauf wetten, dass wir verantwortungsbewusst sind und es auch in absehbarer Zeit bleiben werden ;)