Next.js 页面构建器 — GrapesJS 集成指南

打造用户真正能上线发布的现代可视化编辑器

22k+
GitHub 星标
100+
插件
MIT
许可证
10yrs+
生产环境使用
Next.js + GrapesJS 蓝图

无需与 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
// 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 构建器平台

多租户存储、模板市场、用量配额、审计日志,以及工作区级别的品牌定制。

分步集成指南

1

安装 GrapesJS

在你的 Next.js 项目中运行 npm install grapesjs。已内置 TypeScript 类型。

2

创建仅客户端的编辑器组件

创建 GrapesEditorClient.tsx,在 useEffect 钩子中通过 DOM ref 初始化 GrapesJS。

3

用 next/dynamic 包装(ssr: false)

使用 dynamic(() => import("./GrapesEditorClient"), { ssr: false }) 来阻止在服务端执行。

4

将存储连接到 API 路由

使用 editor.getHTML() 和 editor.getCSS() 将内容提交到 Next.js API 路由、Vercel KV 或 Supabase。

面向 Next.js 项目的推荐插件

存储$19

Storage REST API

将 GrapesJS 连接到 Next.js API 路由以实现持久化

区块$29

Blocks Library Pro

为 Next.js 页面构建器提供可直接投产的区块库

邮件免费

GrapesJS MJML Preset

在你的 Next.js 应用中构建响应式邮件模板

导出免费

Export Plugin

直接在 Next.js API 路由中导出干净的 HTML/CSS

存储集成示例

Vercel KV

app/api/page/route.ts
// 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

lib/savePage.ts
// 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 });
}

准备好打造你的可视化构建器体验了吗?

从久经考验的插件起步,再逐层叠加面向团队、客户和发布审批的自有工作流。

探索插件生态