¿Por qué combinar GrapesJS con Svelte?
GrapesJS es un constructor de arrastrar y soltar con licencia MIT y agnóstico respecto al framework, así que
se inserta en una app de SvelteKit sin biblioteca de envoltorios. La única regla que hay que respetar
es que GrapesJS necesita el DOM — debe ejecutarse en el navegador, no durante
Renderizado del lado del servidor. El ciclo de vida de onMount Slente hace que
Trivial: solo dispara en el cliente, que es exactamente donde debe estar el editor.
Esta guía cubre una configuración lista para producción: instalar, montar el editor de forma segura, Persiste contenido en tu backend y exporta HTML y CSS limpios.
1. Instalar GrapesJS
npm install grapesjs
No se requiere ningún adaptador específico para Svelte. Puedes añadir presets más adelante (por ejemplo
grapesjs-preset-webpage o el
plugins de GJS. Market) una vez que se ejecuta el editor principal.
2. Montar el editor en el lado del cliente
Crea una ruta, por src/routes/editor/+page.svelteejemplo . Vincular a
elementocontenido, luego inicializa GrapesJS dentro onMount de y
Devuelve su desmontaje para que la instancia se destruya en la navegación.
<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>
Como onMount nunca se ejecuta en el servidor, se crea el editor
solo en el navegador — sin errores SSR, sin window is not defined.
3. Persiste contenido en tu backend
El enfoque más sencillo es un botón de guardar que lea el documento actual y Lo PUBLICA en tu 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>
¿Prefieres guardados automáticos? Configurar el Administrador de Almacenamiento en lugar de
storageManager: false:
storageManager: {
type: 'remote',
stepsBeforeSave: 3,
options: {
remote: {
urlStore: '/api/pages',
urlLoad: '/api/pages/load',
},
},
}
4. Exportación de producción HTML y CSS
editor.getHtml() y editor.getCss() devolver el
marcado y estilos renderizados como cadenas. Combínalos cuando necesites uno independiente
Documento:
const html = editor.getHtml();
const css = editor.getCss();
const document = `<!doctype html>
<html>
<head><style>${css}</style></head>
<body>${html}</body>
</html>`;
Recargar un proyecto guardado
Para volver a abrir una página en el editor, pasa los datos almacenados del proyecto de vuelta a través de
editor.loadProjectData(saved.project) después de init, o set
projectData En la configuración de iniciación.
Requisitos previos
Antes de empezar, asegúrate de tener Node.js 18 o más reciente y un SvelteKit
proyecto creado con npm create svelte@latest. No necesitas ninguno
Envoltorio específico de GrapesJS para Svelte — GrapesJS es independiente del framework y se distribuye como un
módulo ES simple, así que el mismo enfoque funciona en una app SvelteKit, una Svelte simple
SPA, o un componente Svelte incrustado en una página más grande. Una comprensión básica de
Ciclo de vida de Slente (onMount, onDestroy) y de donde
El código se ejecuta (servidor vs navegador) es todo lo que necesitas para seguir.
Añadir bloques personalizados al editor
Un editor básico no es muy útil hasta que tus usuarios tienen bloques de construcción que arrastrar
Al lienzo. Regístralos en el Gestor de Bloques justo después
grapesjs.init. Cada bloque es una etiqueta más el HTML (o un componente
definición) se deja caer en la página:
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>',
});
Agrupa los bloques relacionados con la category propiedad para que el panel se mantenga
organizado, y buscan bibliotecas de bloques y presets listos para usar de GJS. Mercado
Cuando quieres un set inicial más rico sin tener que construir cada bloque a mano.
Persistir hasta un backend real (profundización)
En una app de SvelteKit, el lugar natural para recibir una partida guardada es un
+server.js Punto final. Haz una transferencia del Storage Manager a él y envía tu
Token de autenticación en los encabezados de la solicitud:
// 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' });
}
Para control total puedes registrar un adaptador de almacenamiento personalizado en lugar del mando a distancia preset — útil cuando necesitas una interfaz optimista, colas offline o una tienda que no sea HTTP:
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' }
Consejos de rendimiento
GrapesJS es una dependencia considerable, así que cárgalo solo donde sea necesario. Importación
es dinámicamente dentro onMount de (await import('grapesjs'))
Lo mantiene fuera de tu paquete principal y de la ruta de renderizado del servidor. Siempre lagrima
el editor abajo con editor.destroy() cuando el componente se desmonta —
durante la navegación del lado del cliente de SvelteKit, una instancia filtrada mantiene a sus oyentes
y nodos DOM vivos, y se acumulan. Afina stepsBeforeSave así
El guardado automático no se activa con cada pequeño cambio, y los plugins cargados de forma perezosa solo cuando
Un usuario realmente abre la función que lo necesita.
Consideraciones de seguridad
GrapesJS almacena fielmente cualquier margen de margen que haya en el lienzo, así que trata exportado HTML como no confiable si los usuarios no administradores pueden editar páginas: sanitizarlo en la salida (a desinfectante validado para el servidor) antes de entregarlo a otros visitantes. Proteger a la Guardar endpoint con autenticación real y autorización — nunca aceptar un POST no autenticado que sobrescribe una página. Si cargas plugins de terceros en El editor, fija sus versiones y las revisa, ya que funcionan con acceso completo al editor y a la página.
Resolución de errores comunes
"document is not definit" significa GrapesJS ejecutado durante SSR — move
el importado y init dentro onMountde . El lienzo
que se vea sin estilo significa que falta la importación de la hoja de estilo; Añadir
import 'grapesjs/dist/css/grapes.min.css'. El editor es
En blanco normalmente significa que el elemento contenedor aún no estaba vinculado cuando
init ran — enjótalo con bind:this e init en
onMount. Si fallan las partidas guardadas con 413 , el proyecto significa que el proyecto
la carga útil supera el límite de tamaño corporal de tu servidor; Súbelo en el punto final.
Cuándo usar GrapesJS con Svelte
GrapesJS es la decisión correcta cuando necesitas incrustar una página visual real o un correo electrónico constructor dentro de tu producto Svelte — un editor de páginas SaaS, una superficie CMS, un Compositor de boletín — y quieres poseer el editor, su almacenamiento y su HTML Salida. Si solo necesitas edición de texto enriquecido dentro de un solo campo, un mechero El componente de texto enriquecido es una mejor opción. Para composición a página completa con arrastrar y soltar layout, un gestor de estilo y una exportación limpia en HTML/CSS, GrapesJS te ofrece mucho más que un editor de texto sin perder licencia y autoalojamiento del MIT.
Trampas comunes en SvelteKit
Tres errores explican casi todas las configuraciones rotas. Primero, importar GrapesJS en la parte superior del módulo en lugar de dentro onMount — eso lo ejecuta durante SSR y lanza document is not defined. Mantén la importación perezosa (await import('grapesjs')) dentro del gancho del ciclo de vida. Segundo, olvidar devolver: editor.destroy()con el enrutamiento del lado del cliente de SvelteKit, el componente se vuelve a montar con frecuencia, y las instancias filtradas del editor acumulan oyentes y memoria. Tercero, falta la hoja de estilo: sin grapesjs/dist/css/grapes.min.css el lienzo se renderiza sin estilo y parece roto. Arregla esos tres y la integración es estable en navegación, recargas en caliente y compilaciones en producción.
Próximos pasos
Una vez que el editor central esté funcionando, extiéndelo con bloques y plugins. Véase el relacionado Guías marco para GrapesJS en React y GrapesJS en Vue, mira los listos para usar Plugins y plantillas de GrapesJS, o prueba el editor directamente del GJS. Página principal del mercado.
Preguntas frecuentes
¿GrapesJS funciona con renderizado SvelteKit en servidor?
Sí. GrapesJS necesita el DOM, así que montarlo dentro onMountde , que solo
Funciona en el navegador. La ruta alrededor de ella aún puede renderizarse en servidor; solo el
La instancia del editor es solo para clientes.
¿Cómo guardo contenido de GrapesJS en una app Svelte?
Usa el Gestor de Almacenamiento para type: 'remote' POST los datos del proyecto para
tu backend, o leer editor.getHtml() y
editor.getCss() Con un botón de guardar y envíalos tú mismo.
¿Necesito destruir el editor al desmontar?
Sí. Retorno editor.destroy() de onMount so GrapesJS
elimina sus oyentes y nodos DOM durante la navegación del lado del cliente, evitando
fugas de memoria.
