Wenn Sie versuchen, [1] in Ihrer Single Page Application (SPA) zu implementieren, die keine serverseitig gerenderten Seiten bereitstellt, werden Sie letztendlich auf Probleme stoßen, siehe: [2]
Nach einigem Tüfteln möchte ich den folgenden Ansatz vorstellen. Das Beispiel ist in Vue.js, kann aber leicht an andere Frameworks/Bibliotheken angepasst werden.
Hinweis: Ich werde den Begriff Blogbeiträge verwenden, wo ein Discourse-Kommentarbereich eingebettet werden soll. Dies kann aber natürlich auch einzelne Seiten Ihrer Website bedeuten.
1. Die Probleme in [1]
1.1. javascripts/embed.js kann nicht mit clientseitig gerendertem Inhalt arbeiten
Der <script>...</script>-Snippet, den Sie in [1] zum Einfügen in Ihr HTML erhalten, wird daher nicht Teil der Implementierung sein, die wir hier verfolgen. Wir werden einige Teile von javascripts/embed.js, die von Ihrer Discourse-Instanz bereitgestellt werden, als Funktionen innerhalb unserer SPA verwenden.
1.2. Discourse kann clientseitig gerenderten Inhalt nicht scrapen
Discourse erstellt automatisch Themen für jeden Blogbeitrag und versucht, auf die ursprüngliche URL (eines Blogbeitrags) zuzugreifen, um Titel und Inhalt zu ermitteln. Dies schlägt bei einer SPA fehl, da Discourse den Nicht-JavaScript-Teil davon erhält, z. B. Wir entschuldigen uns, aber diese Seite funktioniert ohne aktivierten JavaScript nicht richtig. Bitte aktivieren Sie ihn, um fortzufahren.
Wir werden das RSS Polling Plugin verwenden, um die notwendigen Daten bereitzustellen und die Themen für uns zu erstellen.
2. Die Implementierung
2.1 RSS Polling und der RSS/Atom-Feed
Erstellen Sie einen Endpunkt auf Ihrer Website, der einen RSS- oder Atom-Feed für das RSS Polling Plugin bereitstellt. Dieser Endpunkt kann entweder nur eine statische XML-formatierte Datei oder eine serverseitige Funktion sein, die den XML-formatierten Inhalt bereitstellt, Beispiel:
URL: https://mysite.com/blog.atom
Inhalt:
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>My Site Blog Posts</title>
<link href="https://mysite.com/blog/"/>
<updated>2022-07-03T09:02:48.721Z</updated>
<id>urn:uuid:790c1857-b968-49cc-9fbd-bf7afe3552c2</id>
<entry>
<title>An Article about Technology</title>
<author>
<name>Your Name Here</name>
</author>
<link href="https://mysite.com/blog/an-article-about-technology"/>
<id>urn:uuid:f6cc13e4-d2eb-4385-af28-c867a94f48dc</id>
<published>2022-07-03T00:00:00Z</published>
<updated>2022-07-03T00:00:00Z</updated>
<summary>Let's discuss some technology in this article.</summary>
</entry>
</feed>
Installieren Sie das RSS Polling Plugin für Discourse gemäß [3] (Discourse gehostet) oder [4] (selbst gehostet)
Empfohlene Einstellungen für RSS Polling in Admin → Einstellungen → Plugins:
| Schlüssel | Wert |
|---|---|
| rss polling enabled | true |
| rss polling frequency | 10 (d. h. 10 Minuten) |
Fügen Sie einen neuen Feed in der RSS Polling Plugin-Konfiguration unter Admin → Plugins → RSS Polling hinzu.
Konfigurieren Sie ihn gemäß [3]:
| Schlüssel | Wert |
|---|---|
| URL | https://mysite.com/blog.atom |
| Category Filter | <dies ist optional> |
| Author | <definieren Sie einen Autor der automatisch generierten Themen> |
| Category | <definieren Sie die Kategorie(n), in der/denen die automatisch generierten Themen gepostet werden> |
| Tags | <dies ist optional> |
2.2 SPA Router-Konfiguration
Discourse verwendet den letzten Teil des URL-Pfads als Identifikator für einen einzelnen Blogbeitrag.
Beispiele:
https://mysite.com/blog/an-article-about-technology
https://mysite.com/blog/another-article-about-cats
Konfigurieren Sie Ihren SPA-Router entsprechend, sodass einzelne Blogbeiträge einzelnen URLs entsprechen.
Außerdem: Discourse stellt einen Link zurück zum einzelnen Blogbeitrag bereit, daher ist es eine gute UX, wenn Ihre Website beim Klicken den tatsächlichen Artikel anzeigt.
2.3 Die Artikel-Komponente
Wie bereits erwähnt, können wir nicht den Ansatz mit dem <script></script> aus [1] verwenden. Daher implementieren wir den iframe und einige Funktionen aus javascripts/embed.js in unserer Komponente:
Article.vue
Dinge, die Sie bearbeiten sollten:
| Element | Beschreibung |
|---|---|
| #YOUR-DISCOURSE-URL# | die URL Ihrer Discourse-Instanz, z. B. discourse.mysite.com) |
| #YOUR-SITE-URL# | die URL Ihrer Website, z. B. mysite.com möglicherweise auch %2Fblog%2F, wenn der Pfad Ihrer Blogbeiträge nicht /blog/ ist |
<template>
<div id="article">
<!-- Ihr formatierter Artikel hier -->
<iframe
v-if="slug"
v-bind:src="`https://#YOUR-DISCOURSE-URL#/embed/comments?embed_url=https%3A%2F%2F#YOUR-SITE-URL#%2Fblog%2F${slug}%2F`"
id="discourse-embed-frame"
width="100%"
v-bind:height="`${iframeHeight}px`"
frameborder="0"
scrolling="no"
referrerpolicy="no-referrer-when-downgrade"
/>
</div>
</template>
<script>
export default {
data: () => ({
slug: null, // der Slug des Blogbeitrags, z. B. "an-article-about-technology", während die Route "https://mysite.com/blog/an-article-about-technology" ist
iframeHeight: 0 // Discourse wird uns die genaue iframe-Höhe mitteilen (siehe: receiveMessage Methode)
}),
methods: {
// iframe-Kommunikation
receiveMessage(event) {
if (!event) {
return;
}
if (!(event.origin || "").includes("#YOUR-DISCOURSE-URL#")) {
return;
}
if (event.data) {
if (event.data.type === "discourse-resize" && event.data.height) {
this.iframeHeight = +event.data.height;
}
if (event.data.type === "discourse-scroll" && event.data.top) {
// iframe-Offset finden
const destY = this.findPosY(this.$refs["discourse-embed-frame"]) + event.data.top;
window.scrollTo(0, destY);
}
}
},
// Danke http://amendsoft-javascript.blogspot.ca/2010/04/find-x-and-y-coordinate-of-html-control.html
findPosY(obj) {
var top = 0;
if (obj.offsetParent) {
while (1) {
top += obj.offsetTop;
if (!obj.offsetParent) break;
obj = obj.offsetParent;
}
} else if (obj.y) {
top += obj.y;
}
return top;
}
},
async created() {
this.slug = this.$router.currentRoute.path.split("/")[2];
},
mounted() {
window.addEventListener("message", this.receiveMessage);
},
beforeDestroy() {
window.removeEventListener("message", this.receiveMessage);
}
}
</script>
2.4 Discourse Embed-Konfiguration
Nun, da das RSS/Atom-Feed-Polling eingerichtet ist und die Implementierung auf Ihrer Website vorhanden ist, können wir endlich die Einbettung auf der Discourse-Instanz konfigurieren.
Gehen Sie zu Admin → Anpassen → Einbetten und fügen Sie einen Host hinzu:
| Schlüssel | Wert |
|---|---|
| Allowed Hosts | Ihre Website-Basis-URL, z. B. “mysite.com” |
| Class Name | optionaler Klassenname für Styling |
| Path Allowlist | z. B. “/blog/.*” |
| Post to Category | dieselbe Kategorie wie in RSS Polling Category konfiguriert |
3. Abschließende Bemerkungen
Das RSS/Atom-Feed-Polling sowie Discourse selbst erstellen ein neues Thema, wenn es für den einzelnen Blogbeitrag nicht existiert. Stellen Sie sicher, dass das RSS/Atom-Feed-Polling zuerst erfolgt (d. h. warten Sie, bis das Thema erstellt ist, bevor Sie den Blogbeitrag auf Ihrer Website besuchen).
Grund: Discourse kann den Titel und die Zusammenfassung nicht scrapen, daher wäre das Thema mysite.com mit der Zusammenfassung Wir entschuldigen uns, aber diese Seite funktioniert ohne JavaScript nicht. ![]()
Wenn Discourse aus irgendeinem Grund zuerst kam, können Sie das Thema einfach löschen und warten, bis der RSS/Atom-Feed aktiv wird.
Viele Grüße
– MK2k