mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
Every plugin iframe loaded /plugin-sandbox, a force-dynamic Next page. Each frame then fetched, parsed and hydrated Next's client router on top of React and the runtime, and the server rendered the page once per frame, one after another when a dozen plugins started together. Sandboxed frames have opaque origins, so the browser's code cache never helps, and they run on the host page's main thread: with 12 plugins the frames took 2.5-3 s to come up after the app had loaded. The sandbox routes now return a small HTML page with the UI kit's stylesheet and the runtime as an ES module, both built ahead of time: - `scripts/build-plugin-sandbox.mjs` bundles the runtime with esbuild and compiles `plugin-kit.css` with the app's Tailwind setup into `public/plugin-sandbox-assets/`, with a manifest. Named Tabler imports are pointed at the icons' own files, so the full icon set stays in a chunk that only loads for an icon name the kit doesn't ship. - `npm run build`, `npm run dev`, the Dockerfile and the perf-guard workflow run it before `next build`. - `lib/plugin-sandbox/sandbox-document.ts` writes the page; proxy.ts still sets the sandbox CSP and the script carries its nonce. - The assets are served from public/ with CORS and immutable caching. A frame on an idle page is ready in 255 ms instead of 362 ms, eleven at once in 1.0 s instead of 2.1 s.
116 lines
3.7 KiB
JSON
116 lines
3.7 KiB
JSON
{
|
|
"name": "bulwark-webmail",
|
|
"version": "1.17.2",
|
|
"description": "Bulwark Webmail - a modern webmail client built for Stalwart Mail Server",
|
|
"author": "Bulwark Mail <dev@bulwarkmail.org>",
|
|
"license": "AGPL-3.0-only",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+https://github.com/bulwarkmail/webmail.git"
|
|
},
|
|
"homepage": "https://github.com/bulwarkmail/webmail",
|
|
"bugs": {
|
|
"url": "https://github.com/bulwarkmail/webmail/issues"
|
|
},
|
|
"keywords": [
|
|
"jmap",
|
|
"webmail",
|
|
"stalwart",
|
|
"email",
|
|
"nextjs",
|
|
"react",
|
|
"typescript"
|
|
],
|
|
"scripts": {
|
|
"dev": "node scripts/build-plugin-sandbox.mjs && next dev --turbopack",
|
|
"build": "node scripts/build-plugin-sandbox.mjs && next build --turbopack",
|
|
"build:lite": "node scripts/lite/build.mjs",
|
|
"lite:serve": "node scripts/lite/serve.mjs out 4173",
|
|
"test:lite-smoke": "playwright test -c scripts/lite/smoke/playwright.config.ts",
|
|
"test:lite-smoke:stalwart": "playwright test -c scripts/lite/smoke/playwright.stalwart.config.ts",
|
|
"test:perf-guard": "playwright test -c scripts/perf-guard/playwright.config.ts",
|
|
"start": "next start",
|
|
"lint": "eslint .",
|
|
"lint:fix": "eslint . --fix",
|
|
"test:translations": "vitest run --no-isolate lib/__tests__/translations.test.ts",
|
|
"test:integration": "bash integration/run-tests.sh",
|
|
"prepare": "husky",
|
|
"typecheck": "next typegen && tsc --noEmit"
|
|
},
|
|
"dependencies": {
|
|
"@dnd-kit/core": "^6.3.1",
|
|
"@dnd-kit/sortable": "^10.0.0",
|
|
"@dnd-kit/utilities": "^3.2.2",
|
|
"@noble/curves": "^2.4.0",
|
|
"@noble/hashes": "^2.4.0",
|
|
"@tabler/icons-react": "^3.47.0",
|
|
"@tanstack/react-virtual": "^3.13.24",
|
|
"@tiptap/extension-color": "^3.31.3",
|
|
"@tiptap/extension-heading": "^3.31.3",
|
|
"@tiptap/extension-link": "^3.31.3",
|
|
"@tiptap/extension-paragraph": "^3.31.3",
|
|
"@tiptap/extension-placeholder": "^3.31.3",
|
|
"@tiptap/extension-table": "^3.31.3",
|
|
"@tiptap/extension-table-cell": "^3.31.3",
|
|
"@tiptap/extension-table-header": "^3.31.3",
|
|
"@tiptap/extension-table-row": "^3.31.3",
|
|
"@tiptap/extension-text-align": "^3.31.3",
|
|
"@tiptap/extension-text-style": "^3.31.3",
|
|
"@tiptap/extension-underline": "^3.31.3",
|
|
"@tiptap/pm": "^3.31.3",
|
|
"@tiptap/react": "^3.31.3",
|
|
"@tiptap/starter-kit": "^3.31.3",
|
|
"@tiptap/suggestion": "^3.31.3",
|
|
"clsx": "^2.1.1",
|
|
"date-fns": "^4.1.0",
|
|
"dompurify": "^3.4.12",
|
|
"jalaali-js": "^2.0.0",
|
|
"jszip": "^3.10.1",
|
|
"next": "^16.4.2",
|
|
"next-intl": "^4.13.3",
|
|
"otpauth": "^9.5.0",
|
|
"pdfjs-dist": "^6.0.227",
|
|
"postal-mime": "^2.7.4",
|
|
"qrcode": "^1.5.4",
|
|
"react": "^19.2.5",
|
|
"react-dom": "^19.2.5",
|
|
"sharp": "^0.35.4",
|
|
"tailwind-merge": "^3.4.0",
|
|
"undici": "^7.29.1",
|
|
"zustand": "^5.0.12"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/js": "^9.39.4",
|
|
"@playwright/test": "^1.59.1",
|
|
"@tailwindcss/postcss": "^4.2.4",
|
|
"@testing-library/dom": "^10.4.1",
|
|
"@testing-library/jest-dom": "^6.9.1",
|
|
"@testing-library/react": "^16.3.1",
|
|
"@types/node": "^25.6.0",
|
|
"@types/qrcode": "^1.5.6",
|
|
"@types/react": "^19.2.7",
|
|
"@types/react-dom": "^19.2.3",
|
|
"@typescript-eslint/eslint-plugin": "^8.59.0",
|
|
"@typescript-eslint/parser": "^8.59.0",
|
|
"@vitejs/plugin-react": "^6.0.1",
|
|
"@vitest/ui": "^4.1.12",
|
|
"esbuild": "^0.28.0",
|
|
"eslint": "^9.39.4",
|
|
"eslint-plugin-react": "^7.37.5",
|
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
"fake-indexeddb": "^6.2.5",
|
|
"globals": "^17.5.0",
|
|
"husky": "^9.1.7",
|
|
"jsdom": "^28.1.0",
|
|
"tailwindcss": "^4.2.4",
|
|
"tw-animate-css": "^1.4.0",
|
|
"typescript": "^5.9.3",
|
|
"vitest": "^4.1.12"
|
|
},
|
|
"overrides": {
|
|
"flatted": "^3.4.2",
|
|
"picomatch": "^4.0.4",
|
|
"undici": "$undici"
|
|
}
|
|
}
|