Improve twenty-ui packaging for standalone publishing (#21946)

Quick packaging wins to move twenty-ui closer to a standalone
publishable library.

- Move `react`/`react-dom` to `peerDependencies` (`^19.0.0`) so
consumers provide a single React and we avoid duplicate-React bugs. They
stay in `devDependencies` for the in-repo build, and `vite.config.ts`
now derives the Rollup `external` list from peer deps too so React stays
externalized instead of bundled.
- Declare `type-fest` in `dependencies`. It was a phantom dep (resolved
only via root hoisting) and its types are referenced by the emitted
json-visualizer `.d.ts`, so standalone consumers need it.
- Move build-only `glob` to `devDependencies` and add `typescript` (both
used only by `generateBarrels.ts`).
- Make `tsconfig.json` self-contained by inlining the base compiler
options, and point the Vite `cacheDir`/`optimizeDeps.exclude` at
package-local paths.

Verified: typecheck, build (React confirmed externalized in `dist`, not
inlined), dts emission, and unit tests all pass.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21946?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Raphaël Bosi
2026-06-22 17:09:25 +02:00
committed by GitHub
parent 2276e12c12
commit 8553c574db
4 changed files with 22 additions and 11 deletions
+8 -4
View File
@@ -49,9 +49,12 @@
"@vitejs/plugin-react-swc": "^4.3.1",
"@vitest/browser-playwright": "^4.1.0",
"esbuild": "^0.28.1",
"glob": "^11.1.0",
"jest": "29.7.0",
"jest-environment-jsdom": "30.0.0-beta.3",
"prettier": "^3.1.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"sass": "^1.83.0",
"sass-embedded": "^1.83.0",
"size-limit": "^12.1.0",
@@ -59,6 +62,7 @@
"storybook-addon-pseudo-states": "^10.3.3",
"ts-jest": "^29.1.1",
"tsx": "^4.19.3",
"typescript": "^5.9.3",
"vite-plugin-checker": "^0.10.2",
"vite-plugin-dts": "^4.5.4",
"vite-plugin-sass-dts": "^1.3.31",
@@ -75,15 +79,15 @@
"clsx": "^2.1.1",
"date-fns": "^4.4.0",
"framer-motion": "^11.18.0",
"glob": "^11.1.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-responsive": "^9.0.2",
"react-router-dom": "^6.4.4",
"type-fest": "^4.10.1",
"zod": "^4.1.11"
},
"peerDependencies": {
"monaco-editor": ">= 0.25.0 < 1"
"monaco-editor": ">= 0.25.0 < 1",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"scripts": {
"build": "npx vite build"
+4 -1
View File
@@ -6,7 +6,10 @@ import tsconfigPaths from 'vite-tsconfig-paths';
import packageJson from './package.json';
const depNames = Object.keys(packageJson.dependencies || {});
const depNames = Object.keys({
...(packageJson.dependencies || {}),
...(packageJson.peerDependencies || {}),
});
const isExternal = (id: string): boolean =>
depNames.some((dep) => id === dep || id.startsWith(dep + '/'));
+5 -5
View File
@@ -57,9 +57,10 @@ export default defineConfig(({ command }) => {
const BUNDLED_DEPS = ['@tabler/icons-react'];
const externalDeps = Object.keys(packageJson.dependencies || {}).filter(
(dep) => !BUNDLED_DEPS.includes(dep),
);
const externalDeps = Object.keys({
...(packageJson.dependencies || {}),
...(packageJson.peerDependencies || {}),
}).filter((dep) => !BUNDLED_DEPS.includes(dep));
return {
resolve: {
@@ -88,7 +89,6 @@ export default defineConfig(({ command }) => {
},
},
optimizeDeps: {
exclude: ['../../node_modules/.vite', '../../node_modules/.cache'],
// Pre-bundle React up front so Vite's dep optimizer doesn't re-bundle it
// mid-run during browser-mode Storybook tests — re-bundling rotates the
// optimized chunk hash and 404s in-flight dynamic imports (vite 8 / rolldown).
@@ -101,7 +101,7 @@ export default defineConfig(({ command }) => {
],
},
root: __dirname,
cacheDir: '../../node_modules/.vite/packages/twenty-ui',
cacheDir: 'node_modules/.vite',
assetsInclude: ['src/**/*.svg'],
plugins: [
react(),
+5 -1
View File
@@ -54426,6 +54426,8 @@ __metadata:
storybook-addon-pseudo-states: "npm:^10.3.3"
ts-jest: "npm:^29.1.1"
tsx: "npm:^4.19.3"
type-fest: "npm:^4.10.1"
typescript: "npm:^5.9.3"
vite-plugin-checker: "npm:^0.10.2"
vite-plugin-dts: "npm:^4.5.4"
vite-plugin-sass-dts: "npm:^1.3.31"
@@ -54435,6 +54437,8 @@ __metadata:
zod: "npm:^4.1.11"
peerDependencies:
monaco-editor: ">= 0.25.0 < 1"
react: ^19.0.0
react-dom: ^19.0.0
languageName: unknown
linkType: soft
@@ -54611,7 +54615,7 @@ __metadata:
languageName: node
linkType: hard
"type-fest@npm:^4.18.2, type-fest@npm:^4.21.0, type-fest@npm:^4.26.1, type-fest@npm:^4.27.0, type-fest@npm:^4.31.0, type-fest@npm:^4.39.1, type-fest@npm:^4.41.0, type-fest@npm:^4.6.0":
"type-fest@npm:^4.10.1, type-fest@npm:^4.18.2, type-fest@npm:^4.21.0, type-fest@npm:^4.26.1, type-fest@npm:^4.27.0, type-fest@npm:^4.31.0, type-fest@npm:^4.39.1, type-fest@npm:^4.41.0, type-fest@npm:^4.6.0":
version: 4.41.0
resolution: "type-fest@npm:4.41.0"
checksum: 10c0/f5ca697797ed5e88d33ac8f1fec21921839871f808dc59345c9cf67345bfb958ce41bd821165dbf3ae591cedec2bf6fe8882098dfdd8dc54320b859711a2c1e4