Warum GrapesJS mit Svelte kombinieren
GrapesJS ist ein framework-unabhängiger, vom MIT lizenzierter Drag-and-Drop-Builder, also
Droppt in eine SvelteKit-App ohne Wrapper-Bibliothek. Die einzige Regel, die man respektieren muss
ist, dass GrapesJS das DOM benötigt – es muss im Browser laufen, nicht währenddessen
serverseitiges Rendering. Der Lebenszyklus von onMount Svelte macht das
Triviel: Es wird nur auf den Client geschossen, und genau dort gehört der Editor.
Dieser Leitfaden behandelt ein produktionsbereites Setup: installieren, den Editor sicher montieren, Behalten Sie Inhalte in Ihrem Backend auf und exportieren Sie sauberes HTML und CSS.
1. GrapesJS installieren
npm install grapesjs
Kein Svelte-spezifischer Adapter ist erforderlich. Du kannst später Presets hinzufügen (zum Beispiel
grapesjs-preset-webpage oder die
Plugins von GJS.Market) sobald der Kerneditor läuft.
2. Montage des Editors clientseitig
Erstelle eine Route, z. B. src/routes/editor/+page.svelte. Binde a
Container-Element, dann initialisieren Sie GrapesJS innerhalb onMount und
Bring den Zerlegungsabbau zurück, damit die Instanz bei der Navigation zerstört wird.
<script>
import { onMount } from 'svelte';
import grapesjs from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';
let container; // bound to the editor div
let editor; // GrapesJS instance
onMount(() => {
editor = grapesjs.init({
container,
height: '100vh',
fromElement: false,
storageManager: false, // we wire storage manually in step 3
components: '<h1>Hello from GrapesJS</h1>',
style: 'h1 { font-family: sans-serif; }',
});
// Clean up listeners + DOM when the component unmounts.
return () => editor?.destroy();
});
</script>
<div bind:this={container}></div>
Da onMount er nie auf dem Server läuft, wird der Editor erstellt
nur im Browser – keine SSR-Fehler, keine window is not defined.
3. Halte Inhalte für dein Backend fest
Der einfachste Ansatz ist ein Speicher-Button, der das aktuelle Dokument liest und POSTET es in Ihre API:
<script>
async function save() {
const payload = {
html: editor.getHtml(),
css: editor.getCss(),
// Full editable project (for re-loading into the editor later):
project: editor.getProjectData(),
};
await fetch('/api/pages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
}
</script>
<button on:click={save}>Save</button>
Bevorzugst du automatische Speicherfunktionen? Konfigurieren Sie den Storage Manager anstelle von
storageManager: false:
storageManager: {
type: 'remote',
stepsBeforeSave: 3,
options: {
remote: {
urlStore: '/api/pages',
urlLoad: '/api/pages/load',
},
},
}
4. Export von Produktions-HTML und CSS
editor.getHtml() und editor.getCss() die zurückzugeben
Markup und Stile als Strings gerendert. Kombiniere sie, wenn du ein einzelnes brauchst
Dokument:
const html = editor.getHtml();
const css = editor.getCss();
const document = `<!doctype html>
<html>
<head><style>${css}</style></head>
<body>${html}</body>
</html>`;
Lade ein gespeichertes Projekt neu
Um eine Seite im Editor erneut zu öffnen, übergeben Sie die gespeicherten Projektdaten über
editor.loadProjectData(saved.project) nach init oder Set
projectData In der Init-Konfiguration.
Voraussetzungen
Bevor du anfängst, stelle sicher, dass du Node.js 18er oder neuer und ein SvelteKit hast
Projekt erstellt mit npm create svelte@latest. Du brauchst keine
Svelte-spezifische GrapesJS-Verpackung — GrapesJS ist framework-agnostisch und wird als Deckung ausgeliefert
einfaches ES-Modul, also funktioniert derselbe Ansatz in einer SvelteKit-App, einer einfachen Svelte-App,
SPA oder eine Svelte-Komponente, die in eine größere Seite eingebettet ist. Ein grundlegendes Verständnis von
Sveltes Lebenszyklus (onMount, onDestroy) und von , wobei
Code läuft (Server vs. Browser), das reicht, was du brauchst, um mitzuhalten.
Fügen Sie benutzerdefinierte Blöcke zum Editor hinzu
Ein einfacher Editor ist erst sehr nützlich, wenn deine Nutzer Bausteine zum Ziehen haben
auf die Leinwand. Melde sie direkt danach beim Blockmanager an
grapesjs.init. Jeder Block ist ein Label plus das HTML (oder eine Komponente)
Definition) fällt es auf die Seite:
editor.BlockManager.add('hero', {
label: 'Hero section',
category: 'Sections',
content: `
<section class="hero">
<h1>Headline</h1>
<p>Supporting copy goes here.</p>
<a href="#">Call to action</a>
</section>`,
});
editor.BlockManager.add('two-cols', {
label: 'Two columns',
category: 'Layout',
content: '<div class="row"><div class="cell"></div><div class="cell"></div></div>',
});
Gruppiere verwandte Blöcke mit der category Eigenschaft, sodass das Panel erhalten bleibt
organisiert und griff auf fertige Blockbibliotheken und Presets von GJS.Market
Wenn du ein reicheres Startset willst, ohne jeden Block von Hand zu bauen.
Persisting an einem echten Backend (Deep-Dive)
In einer SvelteKit-App ist der natürliche Ort, um einen Speicherstand zu erhalten, ein
+server.js Endpunkt. Übertragen Sie den Storage Manager darauf und senden Sie Ihren
Authentifizierungstoken in den Anfrageheadern:
// in grapesjs.init(...)
storageManager: {
type: 'remote',
autosave: true,
stepsBeforeSave: 3,
options: {
remote: {
urlStore: '/api/pages',
urlLoad: '/api/pages',
headers: { Authorization: `Bearer ${token}` },
},
},
}
// src/routes/api/pages/+server.js
import { json } from '@sveltejs/kit';
let page = {}; // swap for your database
export async function GET() {
return json(page);
}
export async function POST({ request }) {
page = await request.json(); // the full GrapesJS project
return json({ status: 'ok' });
}
Für volle Kontrolle kannst du einen benutzerdefinierten Speicheradapter anstelle der Fernbedienung registrieren Preset — nützlich, wenn Sie eine optimistische Benutzeroberfläche, Offline-Warteschlangen oder einen Nicht-HTTP-Store benötigen:
editor.Storage.add('svelte-store', {
async load() {
const res = await fetch('/api/pages');
return res.ok ? res.json() : {};
},
async store(data) {
await fetch('/api/pages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
},
});
// then: storageManager: { type: 'svelte-store' }
Aufführungstipps
GrapesJS ist eine beträchtliche Abhängigkeit, also lade es nur dort ein, wo es gebraucht wird. Import
es dynamisch in onMount (await import('grapesjs'))
Das hält es aus deinem Hauptbundle und aus dem Server-Renderpfad heraus. Immer reißen
Der Editor beendet editor.destroy() , wenn die Komponente entkoppelt wird —
während der clientseitigen Navigation von SvelteKit hält eine geleakte Instanz ihre Hörer
und DOM-Knoten leben, und sie sammeln sich an. Stimmt stepsBeforeSave so ein
Autosave schaltet nicht bei jeder kleinen Änderung aus, und Plugins laden nur dann lazy-load-lastige Plugins aus, wenn
Ein Nutzer öffnet tatsächlich die Funktion, die sie benötigt.
Sicherheitsaspekte
GrapesJS speichert den Aufschlag auf der Leinwand treu, also behandeln Sie exportierte HTML als nicht vertrauenswürdig, wenn Nicht-Admin-Nutzer Seiten bearbeiten können: Desinfizieren Sie es bei der Ausgabe (a serverseitigem Desinfektionsmittel) bevor es anderen Besuchern zugänglich gemacht wurde. Schütze die Speichern Sie den Endpunkt mit echter Authentifizierung und Autorisierung – akzeptieren Sie niemals ein nicht authentifiziertes POST, das eine Seite überschreibt. Wenn du Drittanbieter-Plugins in lädst Der Editor pinnen deren Versionen und überprüft sie, da sie mit vollem Zugriff laufen an den Redakteur und die Seite.
Fehlerbehebung häufiger Fehler
"Dokument ist nicht definiert" bedeutet, dass GrapesJS während der SSR lief – Umzug
Der Import und init das Innere onMount. Die Leinwand
Looks unstyled bedeutet, dass der Stylesheet-Import fehlt; Hinzufügen
import 'grapesjs/dist/css/grapes.min.css'. Der Herausgeber ist
Blank bedeutet normalerweise, dass das Containerelement noch nicht gebunden war, als
init ran — binde es mit bind:this und init in
onMount. Saves scheitern mit 413 bedeutet, dass das Projekt
Die Nutzlast überschreitet die Körpergrößenbegrenzung deines Servers; Erhöhe es am Endpunkt.
Wann man GrapesJS mit Svelte verwenden sollte
GrapesJS ist die richtige Wahl, wenn Sie eine echte visuelle Seite oder E-Mail einbetten möchten Builder in Ihrem Svelte-Produkt – ein SaaS-Seiteneditor, ein CMS-Surface, ein Newsletter-Komponist – und du möchtest den Editor, seinen Speicher und sein HTML besitzen Output. Wenn du nur eine Rich-Text-Bearbeitung innerhalb eines einzigen Feldes brauchst, dann ein Feuerzeug Die Rich-Text-Komponente passt besser. Für ganzseitige Kompositionen mit Drag-and-Drop layout, einen Style-Manager und einen sauberen HTML/CSS-Export – GrapesJS bietet dir deutlich mehr als ein Texteditor, während sie weiterhin MIT-lizenziert und selbstgehostet ist.
Häufige Fallstricke bei SvelteKit
Drei Fehler erklären fast jedes defekte Setup. Erstens, indem man GrapesJS am oberen Rand des Moduls importiert und nicht im Inneren onMount – das läuft während SSR und wirft document is not defined. Halte den Import lazy (await import('grapesjs')) im Lebenszyklus-Haken. Zweitens, ich vergesse die Rückkehr editor.destroy(): Mit SvelteKits clientseitiger Routing wird die Komponente oft neu gemountet, und geleakte Editor-Instanzen stapeln sich Hörer und Speicher. Drittens: Das fehlende Stylesheet – ohne grapesjs/dist/css/grapes.min.css Leinwand wirkt das ungestylt und sieht kaputt aus. Behebt man diese drei, ist die Integration stabil bei Navigation, Hot Reloads und Produktions-Builds.
Nächste Schritte
Sobald der Kerneditor läuft, erweitere ihn mit Blöcken und Plugins. Siehe die verwandte Framework-Anleitungen für GrapesJS in React und GrapesJS in Vue, stöbern Sie in Ready-Made GrapesJS-Plugins und Vorlagen oder probieren Sie den Editor aus direkt von der GJS.Market-Startseite.
FAQ
Funktioniert GrapesJS mit serverseitigem Rendering von SvelteKit?
Ja. GrapesJS benötigt den DOM, also montiere ihn darin onMount, was nur
läuft im Browser. Die Route drumherum kann weiterhin servergerendert werden; Nur die
Die Editor-Instanz ist nur clientsbasiert.
Wie speichere ich GrapesJS-Inhalte in einer Svelte-App?
Verwenden Sie den Storage Manager mit type: 'remote' dem POST-Projektdaten, um
Dein Backend, oder lies editor.getHtml() und
editor.getCss() auf eine Speichertaste und sie selbst abschicken.
Muss ich den Editor beim Unmount zerstören?
Ja. Rückkehr editor.destroy() von onMount so GrapesJS
entfernt seine Listener und DOM-Knoten während der clientseitigen Navigation und verhindert so
Gedächtnislecks.
