FlowDrop’s editor is a rich component with many dependencies. This guide covers strategies to minimize bundle impact and ensure smooth performance at scale.
Bundle sizes
Approximate gzip sizes by entry point:
| Entry Point | Approx. gzip size | Notes |
|---|
@flowdrop/flowdrop/core | ~10 KB | Types and utilities only — no heavy deps |
@flowdrop/flowdrop/editor | ~180 KB | Includes @xyflow/svelte, Svelte runtime |
@flowdrop/flowdrop/form | ~25 KB | Form fields without CodeMirror |
@flowdrop/flowdrop/form/code | ~350 KB | Includes CodeMirror and language packs |
@flowdrop/flowdrop/form/markdown | ~300 KB | Includes CodeMirror markdown mode |
@flowdrop/flowdrop/playground | ~200 KB | Editor + session management |
@flowdrop/flowdrop | ~400 KB | Full bundle (avoid in production) |
Use specific entry points rather than @flowdrop/flowdrop to tree-shake unused modules.
Lazy loading the editor
The editor bundle is large. Load it only when the user navigates to the editor page:
// Vanilla JS — dynamic import
async function mountEditor(container) {
const [{ mountFlowDropApp }, { createEndpointConfig }] = await Promise.all([
import('@flowdrop/flowdrop/editor'),
import('@flowdrop/flowdrop/core')
]);
await import('@flowdrop/flowdrop/styles');
return mountFlowDropApp(container, {
endpointConfig: createEndpointConfig('/api/flowdrop')
});
}
React
import React, { Suspense, lazy } from 'react';
const FlowDropEditor = lazy(() => import('./FlowDropEditor'));
export function EditorPage() {
return (
<Suspense fallback={<div>Loading editor...</div>}>
<FlowDropEditor />
</Suspense>
);
}
Where FlowDropEditor is a wrapper component that calls mountFlowDropApp in a useEffect.
Deferring CodeMirror
If you use code or markdown fields but not on every page, load them on demand:
async function mountEditorWithCodeFields(container, endpointConfig) {
// Load form fields that require CodeMirror only when needed
const [{ mountFlowDropApp }, { createEndpointConfig }] = await Promise.all([
import('@flowdrop/flowdrop/editor'),
import('@flowdrop/flowdrop/core')
]);
// This registers code/markdown fields into the registry
await import('@flowdrop/flowdrop/form/code');
await import('@flowdrop/flowdrop/form/markdown');
return mountFlowDropApp(container, { endpointConfig });
}
SSR guard patterns
FlowDrop accesses window, document, and browser APIs — it cannot run on the server. Always guard your mount calls.
SvelteKit
import { browser } from '$app/environment';
import { onMount } from 'svelte';
let app;
onMount(async () => {
if (!browser) return;
const { mountFlowDropApp } = await import('@flowdrop/flowdrop/editor');
app = await mountFlowDropApp(document.getElementById('editor'), { ... });
return () => app?.destroy();
});
Next.js (App Router)
'use client';
import dynamic from 'next/dynamic';
const FlowDropEditor = dynamic(() => import('../components/FlowDropEditor'), { ssr: false });
Nuxt
<template>
<ClientOnly>
<FlowDropEditor />
</ClientOnly>
</template>
Vite optimizeDeps
If you see Failed to resolve import errors during development, exclude FlowDrop from Vite’s pre-bundling:
// vite.config.ts
export default defineConfig({
optimizeDeps: {
exclude: ['@flowdrop/flowdrop', '@xyflow/svelte']
}
});
See the Installation guide for more setup tips.
For workflows with many nodes (50+):
Use batch updates
const { actions } = app.instance.workflow;
// Apply nodes and edges in a single reactive update
actions.batchUpdate({
nodes: [...existingNodes, nodeA, nodeB],
edges: [...existingEdges, edge]
});
Use history transactions
Group related changes into a single undo step:
import { getInstance } from '@flowdrop/flowdrop/editor';
const fd = getInstance();
fd.historyBindings.startTransaction(fd.workflow.current, 'Bulk update');
// ... multiple changes
fd.historyBindings.commitTransaction();
Disable auto-save for programmatic updates
When making many changes programmatically, temporarily disable auto-save:
await mountFlowDropApp(container, {
endpointConfig,
features: {
autoSaveDraft: false, // disable localStorage auto-save
showToasts: false // disable toast notifications
}
});
See Mount API for the full features options.