GrapesJS रीमिक्स में क्यों फिट बैठता है
GrapesJS DOM की आवश्यकता होती है, इसलिए रीमिक्स ऐप में आप इसे अंदर से प्रारंभ करते हैं
useEffect (केवल क्लाइंट) जबकि रीमिक्स के लोडर और क्रियाएं डेटा को संभालती हैं
सर्वर पर. यह मार्गदर्शिका संपादक को माउंट करती है, रीमिक्स क्रिया के माध्यम से सहेजती है, और
एचटीएमएल/सीएसएस निर्यात करता है।
1. संपादक क्लाइंट-साइड को माउंट करें
बनाएँ app/routes/editor.tsx। प्रभाव के अंदर GrapesJS आयात करें ताकि यह
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. रीमिक्स एक्शन में सेव को संभालें
// 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' });
}
क्रिया सर्वर पर चलती है, इसलिए आपका डेटाबेस क्लाइंट ब्राउज़र से बाहर रहता है बंडल।
3. सहेजी गई सामग्री को वापस लोड करें
export async function loader() {
return json(await getPage('home'));
}
// in the effect, after init:
// const saved = await fetch('/editor?_data=...'); editor.loadProjectData(saved.project);
रीमिक्स में आम नुकसान
रीमिक्स का सर्वर/क्लाइंट विभाजन वह जगह है जहां चीजें गलत हो जाती हैं। मॉड्यूल शीर्ष स्तर पर GrapesJS आयात करना इसे एसएसआर के दौरान चलाता है और मार्ग को क्रैश करता है - इसके बजाय इसे गतिशील रूप से अंदर useEffect आयात करें। मार्ग action (सर्वर) में सभी दृढ़ता रखें और कभी भी अपने डेटाबेस क्लाइंट को घटक में आयात न करें, या यह ब्राउज़र बंडल में लीक हो जाता है। यदि आप एक सहेजे गए प्रोजेक्ट को लोड करते हैं, तो इसे loader पढ़ें और init के बाद कॉल editor.loadProjectData() करें - SSR के दौरान संपादक स्थिति को प्रस्तुत करने का प्रयास न करें। अंत में, प्रभाव से वापस लौटें editor.destroy() ताकि क्लाइंट-साइड ट्रांज़िशन संपादक उदाहरणों को ढेर न करें।
आवश्यक शर्तें
आपको Node.js 18+ और एक रीमिक्स 2 ऐप की आवश्यकता होगी। कोई रीमिक्स-विशिष्ट GrapesJS पैकेज नहीं है
आवश्यक - संपादक केवल ब्राउज़र है और रीमिक्स के लोडर/क्रियाएं डेटा को संभालती हैं
सर्वर। मार्गों, useEffectऔर रीमिक्स क्रियाओं से परिचित है
पर्याप्त।
संपादक में कस्टम ब्लॉक जोड़ें
इनिट (प्रभाव के अंदर) के बाद ब्लॉक प्रबंधक के साथ खींचने योग्य ब्लॉक पंजीकृत करें:
editor.BlockManager.add('hero', {
label: 'Hero section',
category: 'Sections',
content: '<section class="hero"><h1>Headline</h1><p>Copy</p></section>',
});
एक समृद्ध सेट के लिए तैयार ब्लॉक पुस्तकालयों और प्रीसेट GJS.Market से खींचें।
भंडारण गहरा-गोता: कार्रवाई + लोडर
सर्वर पर दृढ़ता बनाए रखें। प्रोजेक्ट को रूट पर action पोस्ट करें
और इसे loaderवापस पढ़ें , ताकि आपका डेटाबेस क्लाइंट कभी भी लीक न हो
ब्राउज़र बंडल में:
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
}
प्रारंभ के बाद, किसी पृष्ठ को फिर से खोलने के लिए कॉल करें editor.loadProjectData(saved.project) ।
प्रदर्शन युक्तियाँ
GrapesJS को गतिशील रूप से अंदर useEffect आयात करें ताकि यह बाहर रहे
मुख्य बंडल और सर्वर रेंडर पथ, और वापसी editor.destroy()
इसलिए क्लाइंट-साइड ट्रांज़िशन इंस्टेंस को स्टैक नहीं करते हैं। कोड-स्प्लिट भारी प्लगइन्स के पीछे
वह सुविधा जो उनका उपयोग करती है।
सुरक्षा के मनन
लिखने से पहले कार्रवाई को प्रमाणित और अधिकृत करें - कभी भी स्वीकार न करें अप्रमाणित POST जो किसी पृष्ठ को अधिलेखित करता है. आउटपुट पर संग्रहीत मार्कअप को सैनिटाइज़ करें यदि गैर-व्यवस्थापक संपादित कर सकते हैं। पेलोड आकार को मान्य करें ताकि एक बड़ी परियोजना समाप्त न हो सके स्मृति।
सामान्य त्रुटियों का समस्या निवारण
"विंडो/दस्तावेज़ परिभाषित नहीं है" का अर्थ है GrapesJS एसएसआर के दौरान चलाया गया -
आयात करें और इसे केवल अंदर ही स्थापित useEffectकरें . एक अनस्टाइल
कैनवास का मतलब है कि स्टाइलशीट आयात गायब है। एक रिक्त
संपादक का मतलब है कि कंटेनर रेफरी init पर तैयार नहीं था। जलयोजन चेतावनी
आमतौर पर इसका मतलब है कि आपने एसएसआर के दौरान संपादक राज्य को प्रस्तुत करने का प्रयास किया है।
रीमिक्स के साथ GrapesJS का उपयोग कब करें
GrapesJS फिट बैठता है जब आपका रीमिक्स ऐप एक वास्तविक दृश्य पृष्ठ या ईमेल बिल्डर को एम्बेड करता है उपयोगकर्ता अपने स्वयं के संग्रहण और HTML आउटपुट के साथ नियंत्रण करते हैं। इनलाइन रिच टेक्स्ट के लिए, एक हल्का संपादक पर्याप्त है; लेआउट, स्टाइल और के साथ पूर्ण-पृष्ठ रचना के लिए स्वच्छ निर्यात, GrapesJS मजबूत, एमआईटी-लाइसेंस प्राप्त, स्व-होस्टेड विकल्प है।
अगले चरण
संबंधित GrapesJS + React और देखें GrapesJS + Next.js गाइड, ब्राउज़ करें GrapesJS मार्केटप्लेस से शुरू करें, या GJS.Market होम पेज।
अक्सर पूछे जाने वाले प्रश्न
क्या GrapesJS रीमिक्स सर्वर रेंडरिंग के साथ काम करता है?
हाँ - इसे केवल इनिशियलाइज़ useEffect करें ताकि यह ब्राउज़र में चले। द
रूट सर्वर-रेंडर किया गया है; केवल संपादक इंस्टेंस केवल क्लाइंट है।
मैं रीमिक्स में GrapesJS डेटा कैसे सहेजूं?
प्रोजेक्ट डेटा को रीमिक्स एक्शन में पोस्ट करें और इसे अपने डेटाबेस में बनाए रखें। कार्रवाई सर्वर पर चलाएं।
मैं सहेजी गई सामग्री को वापस कैसे लोड करूँ?
सहेजे गए प्रोजेक्ट को लोडर से प्राप्त करें और कॉल करें
editor.loadProjectData(saved) बाद में grapesjs.init।
