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:
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:
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".
Wenn Sie die Seite "spa-home" zur Bearbeitung öffnen, sollten Sie Ihr SPA sehen.
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
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
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
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
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
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
<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
<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.
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
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, }, };
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:
Aufbau einer einfachen SPA mit Magnolia-Vorlagen (Sie sind hier)
Nodes Endpoint API und Commands Endpoint API