Der API-basierte CMS-Ansatz

Avatar of Levi Gable
Levi Gable am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Für jede Art von Inhalt, die Sie für Ihre Website benötigen, entwickeln Sie in drei Schritten

  1. Erstellen Sie den benutzerdefinierten Inhaltstyp und konfigurieren Sie seine Felder
  2. Richten Sie Ihre App so ein, dass sie diese Inhalte aus der API abruft
  3. Laden Sie den Inhalt in Ihre Seitenvorlage

Werfen wir einen genaueren Blick auf jeden dieser Schritte, während ich erläutere, wie Sie eine einfache Nachrichten-Website (Demo-Website) mit einer Homepage und Artikelseiten einrichten.

1) Artikelseiten

Erstellen Sie den benutzerdefinierten Inhaltstyp "Artikel"

Bei der Entwicklung eines benutzerdefinierten Inhaltstyps müssen Sie alle benötigten Inhaltsfelder ermitteln. Ein Blogbeitrag kann beispielsweise eine Kombination aus Text, Bildern und Blockzitaten sein. Für ein Produkt müssten Sie die Bildfelder, Zahlenfelder und Textfelder definieren, die für das Design Ihrer Produktseite spezifisch sind.

Für unsere Artikelseiten benötigen wir eine UID (eindeutige ID für SEO-freundliche URLs), ein Veröffentlichungsdatum, einen Titel, ein Hauptbild, einen Autor und drei verschiedene wiederholbare Abschnitte, die gemischt werden können: Text, Zitate und Bilder.

Der Prozess zum tatsächlichen Erstellen des benutzerdefinierten Typs variiert von CMS zu CMS, aber am Ende erhalten wir einen benutzerdefinierten Typ, der alle Felder enthält, die wir mit Inhalten füllen müssen. So sieht unser benutzerdefinierter Artikeltretyp aus

Das CMS, das ich verwende, ist prismic.io, obwohl jedes CMS, das JSON ausgibt, angepasst werden könnte. CSS-Tricks hat beispielsweise eine Reihe von Artikeln über die WordPress JSON API und es scheint, dass Perch Runway 3 "Headless CMS"-Funktionen haben wird. Prismic verwendet ebenfalls JSON, um Ihre benutzerdefinierten Typen zu erstellen und Ihre Inhaltsfelder zu konfigurieren. Den JSON-Code, den ich für meine benutzerdefinierten Typen für dieses Projekt verwendet habe, finden Sie im Projektpaket auf GitHub. Sie finden ihn im Ordner `customTypes`.

Sobald Sie Ihren benutzerdefinierten Artikeltretyp erstellt und konfiguriert haben, erstellen Sie einige Artikel, und als Nächstes sehen wir, wie Sie die API abfragen, um sie abzurufen.

Richten Sie die Frontend-Anwendung ein, um die API abzufragen und die Artikel zu laden

Hier glänzt ein API-basiertes CMS wirklich. Sie können Ihre Website nach Belieben mit jeder bevorzugten Technologie erstellen. Viele der verfügbaren API-basierten CMS bieten spezifische Entwicklungskits für die wichtigsten Technologien, die alle benötigten Methoden zum Abfragen der API und zum Parsen der zurückgegebenen Daten bereitstellen. Dies erleichtert die schnelle Einrichtung Ihres Projekts.

Unabhängig davon, womit Sie programmieren, müssen Sie die API abfragen, um die anzuzeigenden Inhalte abzurufen. Ich habe diese Beispiel-Website mit dem NodeJS-Entwicklungs-Kit von prismic.io erstellt. Ich habe NodeJS gewählt, weil es eine einfache und unkomplizierte serverseitige JavaScript-Plattform ist.

Lassen Sie uns unsere Anwendung so einrichten, dass die Seiten über ihre UIDs geladen werden. Hier ist ein Beispiel für den Code, den wir zum Abfragen der API für unsere Inhaltseiten verwenden können.

app.route('/:uid').get(function(req, res) {
  var uid = req.params.uid;
  api(req, res).then(function(api) {
    // Here we are querying for a custom type ‘article’ by its unique ID
    return api.getByUID('article', uid);
  }).then(function(pageContent) {
    res.render('article', {
      pageContent: pageContent
    });
  });
});

Laden Sie den Inhalt in die Seitenvorlagen

Sobald wir die benötigten Inhalte aus der API abgerufen haben, müssen wir nur noch die Inhalte in unseren Vorlagen laden. Unsere API-Abfrage liefert ein JSON-Objekt, das alle unsere Inhalte enthält.

Die Entwicklungskits enthalten auch Hilfsfunktionen, die das einfache Laden von Inhalten in unsere Vorlagen erleichtern.

Diese Beispielwebsite verwendet das Pug (früher Jade) Templating-System zur Erstellung des HTML für die Seiten. Die Integration der Seiteninhalte ist schnell und einfach. Alles, was wir tun müssen, ist, unsere statischen Inhalte durch die aus der API abgefragten Inhalte zu ersetzen.

Unten füge ich den Code zur Integration der Inhalte in die Vorlage ein, aber keine Abschnitte wie Header oder Layout-Dateien. Wenn Sie diese sehen möchten, können Sie sich gerne das vollständige Projekt auf GitHub ansehen.

extends ./layout.pug

block body
  include ./partials/header.pug

  div.article.container
    include ./partials/back.pug
    
    h1
      //- Here we insert the StructuredText field ‘title’ from the custom type ‘article’
      != pageContent.getStructuredText('article.title').asText() || 'Untitled'
    img.article-image(src=pageContent.getImage('article.image').url, class='star')

    - var sliceZone = pageContent.getSliceZone('article.body') || {}
    for slice in sliceZone.slices
      //- Render the right markup for a given slice type.
      case slice.sliceType
        
        // Text Section 
        when 'text'
          div.article-section.text
            != slice.value.asHtml()

        // Quote Section
        when 'quote'
          div.article-section.quote
            span.block-quotation !{slice.value.asText()}

        // Image Section
        when 'image-with-caption'
          - var imageWithCaption = slice.value.toArray()[0]
          - var imageUrl = imageWithCaption.getImage('illustration') ? imageWithCaption.getImage('illustration').url : ''
          - var caption = imageWithCaption.get('caption')
          div.article-section.image
            img(src=imageUrl)
            if caption
              p
                span.image-label !{caption.asText()}
          
    include ./partials/back.pug

Wir zeigen nun erfolgreich die Seiten für unsere Website an! Wir werden diesen gleichen Prozess kurz durchlaufen, um unsere Homepage einzurichten.

2) Homepage & Layout

Erstellen Sie den benutzerdefinierten Inhaltstyp "Layout"

Wir benötigen einen benutzerdefinierten Typ für das Layout der Website. Dieser wird Text für das Logo, den Link zu diesem Artikel und den Text für diesen Link enthalten. Die Homepage selbst wird aus den Inhalten aller Artikel bestehen, sodass wir keinen benutzerdefinierten Typ dafür erstellen müssen.

Rufen Sie die API ab und laden Sie die Homepage

Um alle benötigten Inhalte für die Homepage zu erhalten, rufen wir die API tatsächlich zweimal auf. Einmal, um die Layout-Inhalte abzurufen, und dann noch einmal, um alle Artikel in Kacheln auf der Homepage anzuzeigen. So könnte das mit NodeJS aussehen

// Route for homepage
app.route('/').get(function(req, res) {
  api(req, res).then(function(api) {
    // Query the site-layout content
    api.getSingle("site-layout").then(function(layout) {
      // Then query all the articles and sort by date
      api.query(
        prismic.Predicates.at("document.type", "article"),
        { orderings: '[my.article.date desc]' }
      ).then(function(articles) {
        res.render('homepage', {
          layout: layout,
          articles: articles.results
        });
      }).catch(function(err) {
        handleError(err, req, res);
      });
    }).catch(function(err) {
      handleError(err, req, res);
    });
  });
});

Laden Sie den Inhalt in die Homepage-Vorlage

Dann ist es nur noch eine Frage des Ladens des Layouts und des Artikelinhalts in die Homepage-Vorlage. Um den Layout-Inhalt hinzuzufügen, müssen Sie nur die Datei `header.pug` aktualisieren.

header
  a(href="./")
    p.logo
      != layout.getText('site-layout.logo')
  a.article-link(href=layout.getLink('site-layout.link').url() target="_blank")
    != layout.getText('site-layout.link-text')

Auf der Homepage wird der aktuellste Artikel ganz oben angezeigt. Wir nehmen also den ersten Artikel und laden ihn in diese Vorlage.

div.featured-article-container
  div.featured-article(style="background-image: url(" + article.getImageView("article.image", "featured").url + ");")
    div.featured-content
      h2
        != article.getStructuredText('article.title').asText() || 'Untitled'

      //- display first valid slice text and limit it respecting the end of words.
      - var firstParagraph = article.getFirstParagraph()
      - var firstParagraphInPost = firstParagraph ? firstParagraph.text : ''
      - var textLimit = 100
      - var limitedText = firstParagraphInPost.substr(0, textLimit)
      p.description
        if firstParagraphInPost.length > textLimit
          = limitedText.substr(0, limitedText.lastIndexOf(' ')) + '...'
        else
          = firstParagraphInPost
      a.button.featured-button(href=ctx.linkResolver(article)) Read the article

Dann müssen Sie nur noch die restlichen Artikel integrieren.

div.article-tile
  div.article-tile-image(style="background-image: url(" + article.getImageView('article.image', 'tile').url + ");")
  img.article-tile-mobile-image(src=article.getImageView('article.image', 'tile-mobile').url)
  div.article-tile-content
    h2
      != article.getStructuredText('article.title').asText() || 'Untitled'
    p.meta-info 
      != article.getText('article.author')
      span.date  - 
        != ctx.dateConverter(article.getTimestamp('article.date'))
    //- display first valid slice text and limit it respecting the end of words.
    - var firstParagraph = article.getFirstParagraph()
    - var firstParagraphInPost = firstParagraph ? firstParagraph.text : ''
    - var textLimit = 300
    - var limitedText = firstParagraphInPost.substr(0, textLimit)
    p.description
      if firstParagraphInPost.length > textLimit
        = limitedText.substr(0, limitedText.lastIndexOf(' ')) + '...'
      else
        = firstParagraphInPost
    a.button(href=ctx.linkResolver(article)) Read the article

Nach Abschluss der Integration ziehen wir nun erfolgreich Inhalte aus der API und zeigen sie auf unserer Website an!

3) Andere Verwendungen

Ein weiterer Vorteil der Verwendung von API-basierten CMS ist, dass Sie Inhalte auch in anderen Formaten abfragen und laden können, z. B. für Handy-Apps. Um dies zu demonstrieren, habe ich auch eine iOS-App erstellt, die dieselbe API abfragt und die Nachrichtenartikel auf Ihrem Smartphone anzeigt.

Ich habe die App mit React Native erstellt und bin dabei dem gleichen Prozess wie oben gefolgt. Ich habe React Native gewählt, weil es Ihnen ermöglicht, reichhaltige mobile Benutzeroberflächen nur mit JavaScript zu erstellen. Obwohl ich nur eine iOS-App erstellt habe, macht React Native es auch einfach, Ihre App unter Android auszuführen.

Mit den bereits vorhandenen benutzerdefinierten Typen können Sie mit dem Abfragen der API beginnen. Ich stelle unten einige Beispielcodes zur Verfügung, aber Sie können das gesamte Projekt gerne hier in meinem GitHub-Repository einsehen. Hier ist die Abfrage, um die Inhalte eines Artikels zu erhalten.

// The query for the article
async function article (uid) {
  try {
    const api = await PrismicHelper.getApi()
    const layoutDoc = await api.getSingle('site-layout')
    const articleDoc = await api.getByUID("article", uid)
    return {layoutDoc, articleDoc}
  } catch(error) {
    console.log(error);
    return {};
  }
}

Sobald Sie die Inhalte abgefragt haben, können Sie sie in Ihren Ansichten mit denselben Methoden anzeigen, die wir oben für unsere NodeJS-Website verwendet haben. Auch hier ein Beispiel dafür, wie es aussieht.

<ScrollView>
  <StatusBar
    hidden
  />
  <View style={styles.container}>
    <Text style={styles.logo}>
      {layoutDoc.getText('site-layout.logo')}
    </Text>

    <TouchableHighlight onPress={ () => this._navigate() } underlayColor='rgba(0,0,0,0)'>
      <Text style={styles.back}>&larr; back to list</Text>
    </TouchableHighlight>

    <Text style={styles.title}>
      {article.getStructuredText('article.title').asText()}
    </Text>

    <Image source={{uri: article.getImage('article.image').url}} style={[styles.mainImage, styles.section]} resizeMode="cover"/>

    { !content ?
      <Text>Content is missing, try again later</Text>
    :
      <View style={styles.contentWrapper}>
        {content}

        <TouchableHighlight onPress={ () => this._navigate() } underlayColor='rgba(0,0,0,0)'>
          <Text style={styles.back}>&larr; back to list</Text>
        </TouchableHighlight>
      </View>
    }
  </View>
</ScrollView>

Der Vorteil der Erstellung einer Handy-App, die von der Website getrennt ist, besteht darin, dass Sie eine bessere Verbindung zu Ihrem Publikum herstellen und es ihm erleichtern können, über seine Handys auf Ihre Inhalte zuzugreifen. Sie können es sogar auf die nächste Stufe heben und bei jeder Veröffentlichung eines neuen Artikels Push-Benachrichtigungen senden und Ihr Publikum wirklich auf dem Laufenden halten. Ich fand es sehr einfach, Benachrichtigungen mit Urban Airship zu integrieren.

Ich hoffe, dieser Artikel gibt eine gute Vorstellung davon, was Sie vom API-basierten CMS-Ansatz erwarten können. Ich liebe die Freiheit und das Maß an Kontrolle, das ein API-basiertes CMS bietet. Beginnen Sie mit der Einrichtung Ihrer Inhaltstypen genau für das, was Sie brauchen. Dann können Sie die Technologie und das Templating-System verwenden, das am besten für Sie und Ihr Projekt geeignet ist. Und schließlich verbinden Sie sich mit der API, um Ihre Inhalte einfach in Ihre Vorlagen zu integrieren.