fix(web): keep X6 diagram runtime atomic

This commit is contained in:
tianma-if committed 2026-09-05 23:17:12 +08:00
1 parent abff837238
commit 913a6b9b67
4 files changed
+63 -30

No files matched your search

+47 -24
View File
@@ -59,31 +59,54 @@ const BubbleMenuTransactionRegression = () => {
);
};
const DesktopRendererTest = () => (
<main data-desktop-renderer-test-ready>
<BubbleMenuTransactionRegression />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button aria-label="More actions" title="More actions">
More
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Rename</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
const useDiagramEditorRegressionReady = () => {
const [ready, setReady] = useState(false);
<Select defaultValue="notebook-one">
<SelectTrigger aria-label="Notebook">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="notebook-one">Notebook one</SelectItem>
<SelectItem value="notebook-two">Notebook two</SelectItem>
</SelectContent>
</Select>
</main>
);
useEffect(() => {
let mounted = true;
void import("@/components/DiagramEditorPane").then(() => {
if (mounted) setReady(true);
});
return () => {
mounted = false;
};
}, []);
return ready;
};
const DesktopRendererTest = () => {
const diagramEditorReady = useDiagramEditorRegressionReady();
return (
<main
data-desktop-renderer-test-ready
data-diagram-editor-regression-ready={diagramEditorReady ? "true" : "false"}
>
<BubbleMenuTransactionRegression />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button aria-label="More actions" title="More actions">
More
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Rename</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Select defaultValue="notebook-one">
<SelectTrigger aria-label="Notebook">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="notebook-one">Notebook one</SelectItem>
<SelectItem value="notebook-two">Notebook two</SelectItem>
</SelectContent>
</Select>
</main>
);
};
const root = document.getElementById("desktop-renderer-test-root");
+12 -2
View File
@@ -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)[\\/]/,
+1 -1
View File
@@ -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",
});
+3 -3
View File
@@ -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(/<link rel="modulepreload"[^>]+>/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 }))