fix(web): keep X6 diagram runtime atomic
This commit is contained in:
1 parent
abff837238
commit
913a6b9b67
4 files changed
+63
-30
No files matched your search
@@ -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
@@ -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)[\\/]/,
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
|
||||
|
||||
@@ -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 }))
|
||||
|
||||
Reference in new issue
Block a user