无需与 SSR 斗争,即可上线精致的页面构建器。
GrapesJS 仅能在浏览器中运行,而 Next.js 默认在服务端渲染。本指南为你提供最稳妥的架构方案:仅在客户端启动编辑器、稳定的保存/发布 API,以及用户能快速上手的交互体验。
快速实施清单
- 运行 npm install grapesjs,并在全局加载一次样式
- 将编辑器初始化保留在仅客户端组件中
- 使用 { ssr: false } 的动态导入来禁用 SSR
- 为 API 路由添加自动保存,并为内容数据做好版本管理
- 在经过净化处理的查看路由中渲染已发布的 HTML/CSS
重要提示:GrapesJS 仅支持浏览器环境
GrapesJS 在初始化时会调用浏览器 API(document, window, requestAnimationFrame)。在 Pages Router 中,你必须使用 dynamic() 配合 { ssr: false };'use client' 或在 App Router 中使用 isMounted 守卫。忽略这一步将导致构建时或运行时错误。
仅客户端模式
无论是 Pages Router 还是 App Router,推荐的做法都是将编辑器拆分为两个文件:一个使用 dynamic 来禁用 SSR 的轻量包装组件,以及一个负责初始化 GrapesJS 的仅客户端组件:
// components/GrapesJSEditor.tsx
import dynamic from 'next/dynamic';
const GrapesEditor = dynamic(
() => import('./GrapesEditorClient'),
{ ssr: false, loading: () => <div>Loading editor...</div> }
);
export default function GrapesJSEditor() {
return <GrapesEditor />;
}
// components/GrapesEditorClient.tsx
import { useEffect, useRef } from 'react';
import grapesjs from 'grapesjs';
export default function GrapesEditorClient() {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const editor = grapesjs.init({
container: ref.current!,
storageManager: false,
});
return () => editor.destroy();
}, []);
return <div ref={ref} style={{ height: '100vh' }} />;
}App Router 与 Pages Router 对比
Pages Router(Next.js 12/13)
使用来自 dynamic() 的 next/dynamic,并搭配 { ssr: false }。所有组件默认都是 React 客户端组件,因此唯一要做的就是为 GrapesJS 禁用 SSR。
App Router(Next.js 13+)
在编辑器组件顶部添加 'use client'。你仍可使用 dynamic() 来处理加载状态,或添加一个 isMounted 状态守卫,在组件完成客户端挂载前阻止渲染。
选择你的上线范围
1-2 天完成 MVP
使用默认区块、本地持久化和一个发布端点。最适合内部工具或早期客户试用。
1-2 周完成生产上线
加入区块权限、自动保存、素材上传、修订历史以及基于角色的发布工作流。
SaaS 构建器平台
多租户存储、模板市场、用量配额、审计日志,以及工作区级别的品牌定制。
分步集成指南
安装 GrapesJS
在你的 Next.js 项目中运行 npm install grapesjs。已内置 TypeScript 类型。
创建仅客户端的编辑器组件
创建 GrapesEditorClient.tsx,在 useEffect 钩子中通过 DOM ref 初始化 GrapesJS。
用 next/dynamic 包装(ssr: false)
使用 dynamic(() => import("./GrapesEditorClient"), { ssr: false }) 来阻止在服务端执行。
将存储连接到 API 路由
使用 editor.getHTML() 和 editor.getCSS() 将内容提交到 Next.js API 路由、Vercel KV 或 Supabase。
面向 Next.js 项目的推荐插件
Storage REST API
将 GrapesJS 连接到 Next.js API 路由以实现持久化
Blocks Library Pro
为 Next.js 页面构建器提供可直接投产的区块库
GrapesJS MJML Preset
在你的 Next.js 应用中构建响应式邮件模板
Export Plugin
直接在 Next.js API 路由中导出干净的 HTML/CSS
存储集成示例
Vercel KV
// Save to Vercel KV
import { kv } from '@vercel/kv';
export async function POST(req: Request) {
const { id, html, css } = await req.json();
await kv.set(`page:${id}`, { html, css });
return Response.json({ ok: true });
}Supabase
// Save to Supabase
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!
);
export async function savePage(id: string, html: string, css: string) {
await supabase.from('pages').upsert({ id, html, css });
}