diff --git a/apps/web/src/desktop-renderer-test.tsx b/apps/web/src/desktop-renderer-test.tsx
index 308d5b66..10e5c027 100644
--- a/apps/web/src/desktop-renderer-test.tsx
+++ b/apps/web/src/desktop-renderer-test.tsx
@@ -59,31 +59,54 @@ const BubbleMenuTransactionRegression = () => {
);
};
-const DesktopRendererTest = () => (
-
-
-
-
-
-
-
- Rename
-
-
+const useDiagramEditorRegressionReady = () => {
+ const [ready, setReady] = useState(false);
-
-
-);
+ useEffect(() => {
+ let mounted = true;
+ void import("@/components/DiagramEditorPane").then(() => {
+ if (mounted) setReady(true);
+ });
+ return () => {
+ mounted = false;
+ };
+ }, []);
+
+ return ready;
+};
+
+const DesktopRendererTest = () => {
+ const diagramEditorReady = useDiagramEditorRegressionReady();
+
+ return (
+
+
+
+
+
+
+
+ Rename
+
+
+
+
+
+ );
+};
const root = document.getElementById("desktop-renderer-test-root");
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
index 9a565865..70bdc27c 100644
--- a/apps/web/vite.config.ts
+++ b/apps/web/vite.config.ts
@@ -193,6 +193,7 @@ export default defineConfig({
"**/vendor-mermaid-*.js",
"**/*Diagram-*.js",
"**/*DiagramEditorPane-*.js",
+ "**/vendor-x6-*.js",
"**/vendor-codemirror-*.js",
// PDF.js is loaded only when a PDF preview or thumbnail is rendered.
// Keep its runtime out of the install-time app-shell precache and cache
@@ -233,7 +234,7 @@ export default defineConfig({
},
},
{
- urlPattern: ({ url }) => /\/assets\/(?:.*beautiful-mermaid|vendor-mermaid|.*mermaid\.core|.*Diagram-|vendor-codemirror)/.test(url.pathname),
+ urlPattern: ({ url }) => /\/assets\/(?:.*beautiful-mermaid|vendor-mermaid|.*mermaid\.core|.*Diagram-|vendor-x6|vendor-codemirror)/.test(url.pathname),
handler: "CacheFirst",
options: {
cacheName: "edgeever-optional-diagrams",
@@ -291,7 +292,7 @@ export default defineConfig({
? false
: {
resolveDependencies: (_filename, dependencies) => dependencies.filter((dependency) =>
- !/(?:vendor-code-highlight|vendor-(?:mermaid|D3|tiptap|prosemirror|floating|codemirror|zod)|vendor-radix(?!-slot)|ui-primitives|ui-button-tooltip)/.test(dependency),
+ !/(?:vendor-code-highlight|vendor-(?:mermaid|D3|tiptap|prosemirror|floating|codemirror|x6|zod)|vendor-radix(?!-slot)|ui-primitives|ui-button-tooltip)/.test(dependency),
),
},
rolldownOptions: {
@@ -328,6 +329,15 @@ export default defineConfig({
test: /node_modules[\\/](react|react-dom|scheduler|react-router)[\\/]/,
priority: 40,
},
+ {
+ name: "vendor-x6",
+ test: /node_modules[\\/]@antv[\\/]x6[\\/]/,
+ priority: 39,
+ // X6 initializes registries and plugins through a cyclic module
+ // graph. Size-based splitting can evaluate clipboard storage
+ // before Config is initialized, crashing the lazy diagram editor.
+ // Keep the graph atomic and defer the resulting chunk instead.
+ },
{
name: "vendor-prosemirror",
test: /node_modules[\\/](prosemirror-|orderedmap|rope-sequence)[\\/]/,
diff --git a/scripts/verify-desktop-renderer.mjs b/scripts/verify-desktop-renderer.mjs
index e26a2dc5..97906c88 100644
--- a/scripts/verify-desktop-renderer.mjs
+++ b/scripts/verify-desktop-renderer.mjs
@@ -54,7 +54,7 @@ try {
});
await verifyEntry({
filePath: componentTestPath,
- readySelector: '[data-desktop-renderer-test-ready] [data-bubble-menu-regression-ready="true"]',
+ readySelector: '[data-desktop-renderer-test-ready][data-diagram-editor-regression-ready="true"] [data-bubble-menu-regression-ready="true"]',
label: "Desktop renderer component test",
});
diff --git a/scripts/verify-web-performance.mjs b/scripts/verify-web-performance.mjs
index e3df10ce..0dcc6505 100644
--- a/scripts/verify-web-performance.mjs
+++ b/scripts/verify-web-performance.mjs
@@ -22,7 +22,7 @@ assert.ok(precacheStart >= 0 && precacheEnd > precacheStart, "Web service worker
const precacheManifest = serviceWorker.slice(precacheStart, precacheEnd);
assert.doesNotMatch(precacheManifest, /\{url:"index\.html",/, "Current HTML must not be served by a cache-first precache route");
assert.match(precacheManifest, /index\.html\?edgeever-offline-shell=/, "PWA must retain a versioned offline HTML shell");
-const optionalDiagramPattern = /(?:beautiful-mermaid|vendor-mermaid|mermaid\.core|vendor-codemirror|[^"']*Diagram(?:EditorPane)?-)[^"']*\.js/;
+const optionalDiagramPattern = /(?:beautiful-mermaid|vendor-mermaid|mermaid\.core|vendor-x6|vendor-codemirror|[^"']*Diagram(?:EditorPane)?-)[^"']*\.js/;
assert.doesNotMatch(precacheManifest, optionalDiagramPattern, "Optional diagram chunks must remain out of the initial PWA precache");
assert.doesNotMatch(precacheManifest, /vendor~pdf-[^"']*\.js/, "Optional PDF.js runtime must remain out of the initial PWA precache");
assert.doesNotMatch(precacheManifest, /noto-sans-sc-[^"']*\.woff2/, "Print-only Noto Sans SC shards must remain out of the PWA precache");
@@ -37,7 +37,7 @@ const precacheBytes = precacheURLs
const PRECACHE_BUDGET = 5 * 1024 * 1024;
assert.ok(precacheBytes <= PRECACHE_BUDGET, `PWA precache budget exceeded: ${precacheBytes} > ${PRECACHE_BUDGET}`);
const modulePreloads = indexHtml.match(/]+>/g)?.join("\n") ?? "";
-const initialOptionalPattern = /vendor-code-highlight|vendor-D3|beautiful-mermaid|vendor-(?:mermaid|tiptap|prosemirror|floating|codemirror)|ui-primitives|mermaid\.core|[^"']*Diagram(?:EditorPane)?-/;
+const initialOptionalPattern = /vendor-code-highlight|vendor-D3|beautiful-mermaid|vendor-(?:mermaid|tiptap|prosemirror|floating|codemirror|x6)|ui-primitives|mermaid\.core|[^"']*Diagram(?:EditorPane)?-/;
assert.doesNotMatch(modulePreloads, initialOptionalPattern, "Optional editor and diagram chunks must remain out of the initial HTML modulepreload list");
assert.doesNotMatch(modulePreloads, /ui-button-tooltip/, "Button tooltips must load only when a titled button is rendered");
assert.doesNotMatch(modulePreloads, /vendor-radix(?!-slot)/, "Radix overlays must remain out of the initial HTML modulepreload list");
@@ -48,7 +48,7 @@ const INITIAL_MODULE_PRELOAD_BUDGET = 750 * 1024;
assert.ok(initialModulePreloadBytes <= INITIAL_MODULE_PRELOAD_BUDGET, `Initial modulepreload budget exceeded: ${initialModulePreloadBytes} > ${INITIAL_MODULE_PRELOAD_BUDGET}`);
const DEFAULT_CHUNK_WARNING_BYTES = 500 * 1024;
-const allowedLargeChunkPattern = /^(?:vendor-(?:code-highlight|beautiful-mermaid|mermaid-(?:layout|render)|codemirror)|.*Diagram-).*\.js$/;
+const allowedLargeChunkPattern = /^(?:vendor-(?:code-highlight|beautiful-mermaid|mermaid-(?:layout|render)|codemirror|x6)|.*Diagram-).*\.js$/;
const largeChunks = readdirSync(join(distDirectory, "assets"))
.filter((name) => name.endsWith(".js"))
.map((name) => ({ name, size: statSync(join(distDirectory, "assets", name)).size }))