Cómo integrar GrapesJS en una app de Remix (guía completa 2026)

Incrusta GrapesJS en una app de Remix: móntalo en el lado del cliente en useEffect, guarda contenido en una acción de Remix y exporta HTML/CSS limpio.

DevFuture Development
DevFuture Development
21 de mayo de 2026hace un mes
8 lectura mínimaVistas de 8

Por qué GrapesJS encaja con Remix

GrapesJS necesita el DOM, así que en una app de Remix lo inicializas dentro de la app useEffect (solo para clientes) mientras que los cargadores y acciones de Remix gestionan los datos en el servidor. Esta guía monta el editor, guarda mediante una acción de Remix, y exporta HTML/CSS.

1. Montar el editor en el lado del cliente

Crear app/routes/editor.tsx. Importa GrapesJS dentro del efecto para que sea nunca se ejecuta durante SSR.

import { useEffect, useRef } from 'react';
import 'grapesjs/dist/css/grapes.min.css';

export default function Editor() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    let editor: any;
    (async () => {
      const grapesjs = (await import('grapesjs')).default;
      editor = grapesjs.init({
        container: ref.current!,
        height: '100vh',
        fromElement: false,
        storageManager: false,
        components: '<h1>Hello from GrapesJS</h1>',
      });

      // Persist via a Remix action.
      document.getElementById('save')!.onclick = async () => {
        await fetch('/editor', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            html: editor.getHtml(),
            css: editor.getCss(),
            project: editor.getProjectData(),
          }),
        });
      };
    })();
    return () => editor?.destroy();
  }, []);

  return (
    <>
      <button id="save">Save</button>
      <div ref={ref} />
    </>
  );
}

2. Gestionar la partida guardada en una acción de Remix

// same app/routes/editor.tsx
import type { ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
import { savePage } from '~/models/page.server';

export async function action({ request }: ActionFunctionArgs) {
  const data = await request.json();
  await savePage('home', data);   // your DB write
  return json({ status: 'ok' });
}

La acción se ejecuta en el servidor, por lo que tu cliente de base de datos permanece fuera del navegador Un paquete.

3. Cargar contenido guardado de nuevo

export async function loader() {
  return json(await getPage('home'));
}
// in the effect, after init:
// const saved = await fetch('/editor?_data=...'); editor.loadProjectData(saved.project);

Trampas comunes en Remix

Code on a screen in a dark editor
Inicializar el editor solo en useEffect; Mantener a la Base de Bases en la acción.

La división servidor/cliente de Remix es donde las cosas se torcen. Importar GrapesJS en el nivel superior del módulo lo ejecuta durante SSR y la ruta se bloquea — impórtalo dinámicamente dentro useEffect de la ruta. Mantén toda la persistencia en las action rutas (servidores) y nunca importe tu cliente de base de datos al componente, porque se filtra en el paquete del navegador. Si cargas un proyecto guardado, léelo en el loader y llama editor.loadProjectData() después de init — no intentes renderizar el estado del editor durante el SSR. Por último, regresa editor.destroy() del efecto para que las transiciones del lado del cliente no apilen instancias del editor.

Requisitos previos

Necesitarás Node.js 18+ y una app de Remix 2. No hay ningún paquete específico de Remix de GrapesJS requerido — el editor es solo para navegador y los cargadores/acciones de Remix gestionan los datos en El camarero. La familiaridad con las rutas, useEffect, y acciones de Remix es Basta.

Añadir bloques personalizados al editor

Registrar bloques arrastrables con el Gestor de bloques después de iniciar (dentro del efecto):

editor.BlockManager.add('hero', {
  label: 'Hero section',
  category: 'Sections',
  content: '<section class="hero"><h1>Headline</h1><p>Copy</p></section>',
});

Saca librerías de bloques y presets listos de GJS. Haz marketing para un conjunto más rico.

Inmersión en el almacenamiento: acción + cargador

Mantén la persistencia en el servidor. POST el proyecto a las rutas action y léelo de nuevo desde el loader, para que tu cliente de base de datos nunca filtre En el paquete del navegador:

export async function action({ request }) {
  const data = await request.json();
  await savePage('home', data);          // server-only DB write
  return json({ status: 'ok' });
}
export async function loader() {
  return json(await getPage('home'));    // returns the saved project
}

Después de la iniciativa, llama editor.loadProjectData(saved.project) para reabrir una página.

Consejos de rendimiento

Importa GrapesJS dinámicamente dentro useEffect para que no entre en el main bundle y la ruta de renderizado del servidor, y return editor.destroy() Así que las transiciones del lado del cliente no apilan instancias. Plugins con mucho código dividido detrás La función que los utiliza.

Consideraciones de seguridad

Autentica y autoriza la acción antes de escribir — nunca aceptes un POST no autenticado que sobrescribe una página. Sanitize almacenaba el margen en la salida si Los que no son administradores pueden editar. Valida el tamaño de la carga útil para que un proyecto grande no pueda agotarse memoria.

Resolución de errores comunes

"window/document is not defined " significa que GrapesJS se ejecutó durante SSR — Importarla e initar solo dentro useEffect. Un sin estilo Canvas significa que falta la importación de la hoja de estilo. Un blank editor significa que la referencia del contenedor no estaba lista en init. Advertencias de hidratación normalmente significa que intentaste renderizar el estado del editor durante SSR.

Cuándo usar GrapesJS con Remix

GrapesJS encaja cuando tu app Remix incorpora una página visual real o un generador de correo electrónico los usuarios controlan, con tu propio almacenamiento y salida HTML. Para texto enriquecido en línea, un Un editor más ligero es suficiente; para composición a página completa con maquetación, estilo y exportación limpia, GrapesJS es la opción más fuerte, licenciada por MIT y autoalojada.

Próximos pasos

Véase el GrapesJS + React y Guías de GrapesJS + Next.js , consulta la Mercado GrapesJS, o empieza desde el GJS. Página principal del mercado.

Preguntas frecuentes

¿GrapesJS funciona con el renderizado de Remix server?

Sí — inicialízalo solo en useEffect para que funcione en el navegador. El la ruta se renderiza en el servidor; Solo la instancia del editor es solo para el cliente.

¿Cómo guardo los datos de GrapesJS en Remix?

PUBLICA los datos del proyecto en una acción Remix y mantenlos en tu base de datos. Acciones Ejecuta en el servidor.

¿Cómo vuelvo a cargar contenido guardado?

Recupera el proyecto guardado de un cargador y llama editor.loadProjectData(saved) después grapesjs.initde .

Más etiquetas:
21 de mayo de 2026 publicado
27 de junio de 2026 actualizado
🔌 GJS. Mercado

¿Buscas plugins para GrapesJS?

Más de 100 plugins, presets y plantillas seleccionados — seleccionados cuidadosamente para la calidad y mantenidos por la comunidad.

Comparte esta publicaciónTwitterFacebookLinkedIn
Publicado a través de
DevFuture Development
DevFuture Development
Visita la tienda →

Más de DevFuture Development

Descubre otras publicaciones interesantes y mantente al día con el contenido más reciente.

Ver todas las publicaciones

Plugins premium de DevFuture Development

Añadidos pagados seleccionados a mano por este creador.

Visita la tienda →