Tree-shaking & bundle size
How to keep bundles small when consuming Cynosure.
Tree-shaking & bundle size
Section titled “Tree-shaking & bundle size”Cynosure is authored to be as friendly to tree-shaking as a modern ESM library can be. Here’s how to get the smallest possible bundles.
Use per-component entries
Section titled “Use per-component entries”// Smallest possibleimport { Button } from '@arshad-shah/cynosure-react/button';import { Input } from '@arshad-shah/cynosure-react/input';Each component has its own tsup entry. The barrel (@arshad-shah/cynosure-react) also
tree-shakes with modern bundlers, but per-component imports are a
guarantee: no matter which bundler version you’re on, you only pull in
the subpath you reach for.
CSS rides along automatically
Section titled “CSS rides along automatically”Every per-component JS entry imports its own CSS at the top:
import './core.css';import './button.css';export { Button } from './chunk-….js';So import { Button } from '@arshad-shah/cynosure-react/button' pulls in
exactly the rules Button needs. core.css carries the shared rules used
by 2+ components (layout-prop cascade, typography base, focus ring, the
@property registrations) — your bundler deduplicates it across any
number of per-component imports.
Footprint at the consumer’s bundler:
- Monolithic path:
import '@arshad-shah/cynosure-react/styles.css'→ 31 KB gzip for every Cynosure rule in the library. - One component only: ~20 KB gzip (
core.css+ that component’s rules, which are typically <1 KB on their own). - Many components: 20 KB + the per-component rules you actually use.
For a single bundled file (one <link> tag, no imports to wire up),
@arshad-shah/cynosure-react/all.css ships tokens + components together
(33 KB gzip).
sideEffects
Section titled “sideEffects”Cynosure packages declare sideEffects: ["**/*.css"]. Bundlers drop any JS
file whose only effect is its module graph, while keeping the CSS imports
the components rely on.
Bundle budgets
Section titled “Bundle budgets”pnpm size runs size-limit against every component in the library:
pnpm sizeThe root .size-limit.json defines per-component gzipped budgets. Open a
PR that exceeds a budget → CI fails with a diff showing which component
grew and by how much.
Inspecting what actually ships
Section titled “Inspecting what actually ships”- Vite:
vite build --mode production+vite preview+ DevTools Network panel. - Rollup visualiser:
rollup-plugin-visualizeron your own build. - Next.js:
@next/bundle-analyzer.
Cynosure’s peers (react, react-dom, react-aria-components, and
the four remaining Radix menu packages —
@radix-ui/react-{dropdown-menu,context-menu,menubar,navigation-menu})
must exist once in your graph. If you see duplicated copies, run
pnpm why <pkg> and align the version via your package manager’s
hoisting / catalog.