mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 08:12:43 +00:00
perf: stop loading the app's stores in every plugin frame
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import * as React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from "@/lib/cn";
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from "@/lib/cn";
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// @vitest-environment node
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import path from 'node:path';
|
||||
import { build } from 'esbuild';
|
||||
|
||||
// Every plugin iframe parses and runs all the code the sandbox page imports,
|
||||
// once per frame: sandboxed frames have opaque origins, so the browser's code
|
||||
// cache never helps. The app's stores came in through the UI kit's Button
|
||||
// (lib/utils -> settings store -> ten more stores), which made each frame
|
||||
// boot ~100 ms slower.
|
||||
describe('plugin sandbox runtime', () => {
|
||||
it('does not pull the app stores into plugin frames', async () => {
|
||||
const root = path.resolve(__dirname, '../..');
|
||||
const result = await build({
|
||||
entryPoints: [path.join(root, 'lib/plugin-sandbox/runtime.tsx')],
|
||||
bundle: true,
|
||||
write: false,
|
||||
metafile: true,
|
||||
format: 'esm',
|
||||
platform: 'browser',
|
||||
jsx: 'automatic',
|
||||
alias: { '@': root },
|
||||
external: ['@tabler/icons-react'],
|
||||
loader: { '.css': 'empty' },
|
||||
logLevel: 'silent',
|
||||
});
|
||||
const inputs = Object.keys(result.metafile.inputs).map((f) => f.replace(/\\/g, '/'));
|
||||
expect(inputs.filter((f) => /(^|\/)stores\//.test(f))).toEqual([]);
|
||||
expect(inputs.filter((f) => /node_modules\/zustand\//.test(f))).toEqual([]);
|
||||
}, 30_000);
|
||||
});
|
||||
@@ -221,7 +221,9 @@ describe('plugin dialog footer', () => {
|
||||
await act(async () => {});
|
||||
expect(result).toBeNull();
|
||||
vi.doUnmock('@/components/plugins/plugin-iframe-slot');
|
||||
});
|
||||
// The dialog host is the first import here that loads the app's stores
|
||||
// (the kit no longer does), and transforming them takes a while.
|
||||
}, 30_000);
|
||||
});
|
||||
|
||||
describe('Combobox', () => {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
// Kept apart from lib/utils, which imports the settings store: the plugin
|
||||
// sandbox uses the app's Button and Input, and through lib/utils every
|
||||
// sandbox frame loaded and ran ten app stores it never uses.
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
// against.
|
||||
|
||||
import * as React from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { cn } from '@/lib/cn';
|
||||
import { Button as AppButton } from '@/components/ui/button';
|
||||
import { Input as AppInput } from '@/components/ui/input';
|
||||
import { getFileIconByName, getFolderIcon } from '@/components/files/file-icons';
|
||||
|
||||
+1
-5
@@ -1,5 +1,3 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { Mailbox } from "./jmap/types";
|
||||
import { debug } from "./debug";
|
||||
import { getEffectiveLocale } from '@/i18n/detect-locale';
|
||||
@@ -7,9 +5,7 @@ import { useSettingsStore } from "@/stores/settings-store";
|
||||
import type { DateFormat, DateLocale } from "@/stores/settings-store";
|
||||
import { getEffectiveTimeZone, getWallClock } from "./timezone";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
export { cn } from "./cn";
|
||||
|
||||
/**
|
||||
* Strip embedded Basic-auth credentials from a URL for display.
|
||||
|
||||
Reference in New Issue
Block a user