Kopflose Magnolia: Aufbau einer einfachen SPA mit Magnolia-Vorlagen
Feb. 8, 2022
--
Kopflose Magnolia: Aufbau einer einfachen SPA mit Magnolia-Vorlagen

Kopflose Magnolia: Aufbau einer einfachen SPA mit Magnolia-Vorlagen

Wenn Sie Magnolia als Headless Content Management kennenlernen möchten, aber nicht wissen, wo Sie anfangen sollen, sind Sie hier genau richtig. Im Rahmen unserer Serie "Headless Magnolia" werden wir relevante Funktionen aufschlüsseln, die es Ihnen ermöglichen, Magnolia als Headless CMS zu nutzen.

In diesem Artikel werden wir eine einfache Singe Page Application (SPA) erstellen, die Sie in Magnolia bearbeiten können.

Lokale Installation von Magnolia

Um eine Magnolia-Instanz auf Ihrem lokalen Rechner zu erstellen und zu starten, folgen Sie bitte unserer Dokumentation.

Danach sollten Sie in der Lage sein, sich in Magnolia unter http://localhost:8080/magnoliaAuthor/ einzuloggen und eine brandneue Magnolia-Installation zu sehen:

1_Magnolia_home

Erstellen des SPA-Lichtmoduls

Laden Sie nun unser SPA Light Module herunter, das wir für Sie vorbereitet haben. Entpacken Sie das Archiv und verschieben Sie das Verzeichnis spa in den Ordner light-modules Ihrer lokalen Magnolia-Instanz.

Das Light-Modul enthält YAML-Definitionen für 1 Seite, 3 Komponenten und 1 Bereitstellungsendpunkt:

Java
  spa └── dialogs | └── components | | └── Item.yaml | | └── Text.yaml | └── pages | └── Home.yaml └── restEndpoints | └── delivery | └── pages.yaml └── templates └── components | └── Item.yaml | └── List.yaml | └── Text.yaml └── pages └── Home.yaml  

Ich empfehle Ihnen, alle YAML-Definitionen zu überprüfen, um sich mit der Konfiguration vertraut zu machen.

Einrichten der ersten SPA

Erstellen Sie außerhalb des Magnolia-Ordners ein Basisprojekt mit React, Angular oder Vue und starten Sie es.

Reagieren Sie

npx create-react-app magnolia-spa

npm start

Eckig

ng neue magnolia-spa

ng serve

Vue

vue create magnolia-spa

npm run serve

In der Seitendefinition unter /spa/templates/pages/Home.yaml setzen Sie die baseUrl auf Ihren SPA-Server, zum Beispiel http://localhost:3000 für React.

Erstellen Sie dann eine neue Seite in der Magnolia Pages App unter Verwendung der Vorlage "SPA Home". Nennen Sie sie "spa-home".

2_add_page

Wenn Sie die Seite "spa-home" zur Bearbeitung öffnen, sollten Sie Ihr SPA sehen.

3_SPA_page

Magnolia Front-End-Helfer für SPAs

Um die SPA-Bearbeitung in Magnolia zu ermöglichen, müssen Sie einen Front-End-Helper verwenden. Magnolia bietet von Haus aus 3 Helfer:

Alle Helfer exportieren 3 Wrapping-Komponenten:

  • EditablePage ist die Wrapping-Komponente für Seiten

  • EditableArea ist die Wrapping-Komponente für Bereiche

  • EditableComponent ist die Wrapping-Komponente für Komponenten

The Visual SPA Editor is here

Next-level headless streamlines how marketing and developer teams work and create together.

Verwaltung Ihrer SPA in Magnolia

Stellen wir zunächst sicher, dass anonyme Benutzer Zugriff auf den Seiten-Endpunkt haben. Befolgen Sie dazu die Anweisungen in meinem vorherigen Blogbeitrag in dieser Serie Headless Magnolia: REST Endpunkt Sicherheit und CORS.

Als nächstes installieren Sie den Magnolia-Konnektor für Ihr Framework:

npm install @magnolia/react-editor

npm install @magnolia/angular-editor

npm install @magnolia/vue-editor

Erstellen und ändern Sie nun Ihr SPA-Projekt.

Reagieren Sie

Datei: /magnolia-spa/src/index.js

Java
  import React from 'react'; import ReactDOM from 'react-dom'; import { EditablePage } from '@magnolia/react-editor'; import Home from './pages/Home'; const config = { componentMappings: { 'spa:pages/Home': Home, }, }; class App extends React.Component { state = {}; async componentDidMount() { const nodeName = '/spa-home'; const pagePath = nodeName + window.location.pathname.replace(new RegExp('(.*' + nodeName + '|.html)', 'g'), '') const isPagesApp = window.location.search.includes('mgnlPreview'); let templateAnnotations; const pageRes = await fetch('http://localhost:8080/magnoliaAuthor/.rest/delivery/pages' + pagePath); const page = await pageRes.json(); if (isPagesApp) { const templateAnnotationsRes = await fetch( 'http://localhost:8080/magnoliaAuthor/.rest/template-annotations/v1' + pagePath ); templateAnnotations = await templateAnnotationsRes.json(); } this.setState({ page, templateAnnotations }); } render() { const { page, templateAnnotations } = this.state; return ( <div className='App'>
       {page && config && <EditablePage content={page} config={config} templateAnnotations={templateAnnotations} />} </div>
   ); } } ReactDOM.render( <React.StrictMode>
   <App />
 </React.StrictMode>, document.getElementById('root') );

Datei: /magnolia-spa/src/pages/Home.js

Java
  import React from 'react'; import { EditableArea } from '@magnolia/react-editor'; function Home(props) { const { title, main } = props; return ( <div>
     <h1>{title}</h1>
     {main && <EditableArea content={main}/>} </div>
 ); } export default Home;

Eckig

Datei: /magnolia-spa/src/app/app.module.ts

Java
  import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { MagnoliaModule } from '@magnolia/angular-editor'; import { HomeComponent } from './pages/home.component'; @NgModule({ declarations: [AppComponent, HomeComponent], imports: [BrowserModule, MagnoliaModule], providers: [], bootstrap: [AppComponent], entryComponents: [HomeComponent], }) export class AppModule {}  

Datei: /magnolia-spa/src/app/app.component.ts

Java
  import { Component, Input } from '@angular/core'; import { EditorContextService } from '@magnolia/angular-editor'; import { HomeComponent } from './pages/home.component'; const config = { componentMapping: { 'spa:pages/Home': HomeComponent, }, }; @Component({ selector: 'app-root', template: `<editable-page [content]="content"></editable-page>`, styles: [], }) export class AppComponent { @Input() content: any; constructor(private editorContext: EditorContextService) { this.editorContext.setComponentMapping(config.componentMapping); this.getContent(); } async getContent() { const nodeName = '/spa-home'; const pagePath = nodeName + window.location.pathname.replace(new RegExp('(.*' + nodeName + '|.html)', 'g'), '') const isPagesApp = window.location.search.includes('mgnlPreview'); const contentRes = await fetch('http://localhost:8080/magnoliaAuthor/.rest/delivery/pages' + pagePath); const content = await contentRes.json(); if (isPagesApp) { const templateAnnotationsRes = await fetch( 'http://localhost:8080/magnoliaAuthor/.rest/template-annotations/v1' + pagePath ); const templateAnnotations = await templateAnnotationsRes.json(); this.editorContext.setTemplateAnnotations(templateAnnotations); } this.content = content; }  

Datei: /magnolia-spa/src/app/pages/home.component.ts

Java
  import { Component, Input } from '@angular/core'; @Component({ template: `<div>
   <h1>{{ title }}</h1>
   <div editable-area [content]="main"></div>
 </div>`, }) export class HomeComponent { @Input() title: any; @Input() main: any; }

Vue

Datei: /magnolia-spa/src/App.vue

Java
  <template>
 <EditablePage
   v-if="page"
   v-bind:content="page"
   v-bind:config="config"
   v-bind:templateAnnotations="templateAnnotations"
 />
</template>
<script>
import { EditablePage } from "@magnolia/vue-editor";
import Home from './pages/Home.vue'
const config = {
 componentMappings: {
   'spa:pages/Home': Home,
 },
};
export default {
 name: 'App',
 components: {
   EditablePage
 },
 data() {
   return {
     page: null,
     templateAnnotations: {},
     config,
   };
 },
 async mounted() {
    const nodeName = '/spa-home';
    const pagePath = nodeName + window.location.pathname.replace(new RegExp('(.*' + nodeName + '|.html)', 'g'), '')
   const isPagesApp = window.location.search.includes('mgnlPreview');
   const pageRes = await fetch('http://localhost:8080/magnoliaAuthor/.rest/delivery/pages' + pagePath);
   const page = await pageRes.json();
   if (isPagesApp) {
     const templateAnnotationsRes = await fetch(
       'http://localhost:8080/magnoliaAuthor/.rest/template-annotations/v1' + pagePath
     );
     const templateAnnotations = await templateAnnotationsRes.json();
     this.templateAnnotations = templateAnnotations;
   }
   this.page = page;
 }
}
</script>

Datei: /magnolia-spa/src/components/HelloWorld.vue

Java
  <template>
 <div>
   <h1>{{ Titel }}</h1>
   <EditableArea v-if="main" v-bind:content="main" />
 </div>
</template>
 <script>
import { EditableArea } from '@magnolia/vue-editor';
 export default {
 name: "Home",
 components: {
   EditableArea
 },
 props: ["title", "main"]
};
</script>

Wenn Sie sich diesen Code ansehen, werden Sie feststellen, dass alle Implementierungen 3 Dinge gemeinsam haben:

  • Holen des Seiteninhalts

  • Abrufen von Vorlagenkommentaren

  • Komponenten-Zuordnungen

Der Ausgangspunkt für jede Implementierung ist eine editierbare Seite. EditablePage konsumiert den Inhalt der Seite aus dem Endpunkt pages, den wir im Light-Modul definiert haben.

Beachten Sie, wie der JavaScript-Code den pagePath mit einem regulären Ausdruck und dem Namen des Stammverzeichnisses "spa-home" erstellt.

Das Konfigurationsobjekt componentMappings ist für die Mappings zwischen den Seiten- und Komponentenvorlagen in Magnolia, mgnl:template, und den SPA-Komponenten verantwortlich.

Wenn eine Seite in der Magnolia Pages App angezeigt wird, holt der Code die Template-Anmerkungen ab und setzt sie, um die grünen Bearbeitungsleisten im Magnolia Visual SPA Editor darzustellen.

Der Endpunkt für das Template Annotations, der für die Bereitstellung der Annotationsdaten benötigt wird, wird von Magnolia automatisch erstellt.

Die Seiten-, Bereichs- und Komponenteneigenschaften, die Sie in den Dialogdefinitionen festgelegt haben, werden als Eigenschaften in Ihren SPA-Komponenten angezeigt.

Wenn Ihre Einrichtung abgeschlossen ist, sollten Sie eine einfache Seite haben.

4_sample_page1

Erweitern Sie Ihr Projekt

Versuchen Sie, Listen- und Textkomponenten in den Hauptbereich der Seite einzufügen. Stellen Sie sicher, dass Sie die SPA-Komponenten erstellen, um diese Komponenten zu rendern und sie z. B. in componentMappings zuzuordnen:

Datei: /magnolia-spa/src/components/Text.js

Java
  import React from 'react'; function Text(props) { const { text } = props; return <div>{text}</div>; } export default Text; File: /magnolia-spa/src/index.js import Text from './components/Text'; const config = { componentMappings: { 'spa:pages/Home': Home, 'spa:components/Text': Text, }, };  
5_sample_page2

Das war's. Sie haben eine grundlegende SPA mit Magnolia-Vorlagen erstellt.

Sie können Ihr Projekt weiter ausbauen, indem Sie neue Seiten- und Komponentenvorlagen im Light-Modul erstellen und diese Ihrer SPA zuordnen.

Erfahren Sie mehr über die Headless-Funktionen von Magnolia

Diese Serie über die kopflose Magnolie wird folgende Themen behandeln:

  1. Die Delivery Endpoint API

  2. REST-Endpunkt-Sicherheit und CORS

  3. SPAs für die Bearbeitung in Magnolia konfigurieren

  4. Aufbau einer einfachen SPA mit Magnolia-Vorlagen (Sie sind hier)

  5. Virtuelle URIs abbilden

  6. Nodes Endpoint API und Commands Endpoint API

  7. Vererbung in Headless Magnolia

Über den autor

Bartosz Staryga

Front-End Solution Architect, Magnolia

Bartosz is an expert in headless content management and front-end development at Magnolia. He designs and develops new Magnolia features and supports customers with their headless implementations from content types to APIs to integrations. Bartosz enjoys building new things and seeing them in action. He is also a trainer for Magnolia’s Headless training.