For a component library, what are the trade-offs between publishing one package for all components and publishing one package per component?
answer
- one version versus many
- components that contain components
- version skew on one screen
- entry points as the middle ground
- split out heavy optional parts
basics
~20 sOne package gives consumers a single coherent version and simple upgrades; per-component packages allow independent releases but let an app mix incompatible versions and duplicate shared internals. Many systems ship one package with per-component entry points.
solid answer
~40 sA **single package** means one install and one version number: every component in an app comes from the same release, shared internals such as focus utilities load once, and upgrades are one step. Its costs are that every component releases together and, if the package does not tree-shake, apps may carry unused code. **Per-component packages** let each component release on its own schedule, but they invite **version skew** - a plan card from one release containing a button from another - plus duplicated shared internals and dozens of versions for consumers to manage. Most systems land in the middle: one package with **per-component entry points**, which gives consumers small imports without independent versions, plus separate packages only for genuinely separate concerns such as tokens, icons, or a component with a heavy dependency.
go deeper
Recall that one package means one version for every component, while per-component packages mean many versions an app must keep aligned.
Explain version skew, duplicated internals and why per-component entry points usually give the bundle benefit without the versioning cost.
Show how you would decide which parts - tokens, icons, a heavy chart - deserve their own packages, and how you would keep split packages in lockstep.
Weigh team autonomy in releasing components against consumer coherence, and decide what the package boundaries of the system should follow.
## The two layouts A **component library** can be published as: - **One package** containing every component, versioned as a whole. - **One package per component** - a button package, a plan-card package, a data-usage-meter package - each with its own version. The choice looks like an engineering detail, but it decides what consuming teams experience at every upgrade. ## Side by side | Concern | One package | One package per component | |---|---|---| | Install and upgrade | One dependency, one step | Many dependencies, many steps | | Versioning | One coherent version | Independent versions per component | | Consistency on one screen | Guaranteed | Depends on consumers keeping versions aligned | | Shared internals | Loaded once | May load in several versions | | Bundle size | Small if the package tree-shakes | Small by construction | | Release overhead for the library | One release | Many coordinated releases | One caveat on the bundle row: a single package ships only what the app imports when it is tree-shakeable. If it is not, every component rides along, which is often the real motivation behind splitting. ## What goes wrong with per-component packages - **Version skew.** Components contain components: a plan card renders a button and a badge. If the app pins the plan card at one version and the button at another, one screen shows two generations of the same design. - **Duplicated internals.** Shared utilities - focus management, positioning, token access - may be pulled in at several versions, growing the bundle and sometimes splitting shared state. - **Upgrade fatigue.** Consumers face dozens of version bumps instead of one, and tend to stop upgrading at all. - **Compatibility matrices.** The library must reason about which component versions work together, a problem a single version never has. ## The common middle ground 1. **One package, per-component entry points.** Consumers import each component directly, getting small imports with one coherent version. 2. **Separate packages for separate concerns.** Design tokens, icons and fonts often ship on their own because non-component consumers - a marketing site, a native app, an email template - need them without the components. 3. **Isolate heavy optional components.** A data-usage chart that depends on a large rendering engine gets its own package, so apps that never chart never install it. 4. **If per-component packages are unavoidable, release them in lockstep** with one shared version, so 'version 7' means the same thing for every component. ## Changing layouts later Moving between layouts is itself expensive, which is a reason to choose deliberately early: - **Splitting one package into many** changes every import path in every consuming app, so it arrives as a breaking release, usually with an automated migration. - **Merging many packages into one** removes version skew in a single step, but consumers pinned at different component versions must jump to one aligned release at once. - **Adding entry points** to a single package is additive and backward-compatible, which makes it the cheapest direction to evolve. The cheapest path is usually to start with one package and entry points, and split out only the parts that later prove to need independence. ## When independent packages do make sense - A very large organisation where different teams own components with genuinely different release cadences. - Components with heavy or platform-specific dependencies most consumers never need. - Separate platforms: native mobile components usually ship as their own packages alongside, not inside, the web library, sharing tokens and specifications rather than code. The principle interviewers listen for: package boundaries should follow what consumers need to version independently, and for components that compose one another, that is rarely each component on its own.
- What is version skew and why does it hurt a design system?Version skew is one app running different versions of related packages - a plan card from one release and the button inside it from another. Inconsistencies appear on the same screen, shared internals may load twice, and a bug fixed in one package stays live in another. A single package, or lockstep versions, rules it out.
- When should a component get its own package even in a single-package library?When it drags in a heavy dependency most consumers do not need - a chart with a large rendering engine, a rich-text editor. Isolating it keeps that dependency optional and off the install path of apps that never use it.
- Do per-component entry points give the same bundle benefits as per-component packages?For bundle size, largely yes: importing one entry point pulls only that component and its dependencies, provided the package's side-effect declaration is right. What entry points do not give is independent versioning - which for components that compose one another is usually a benefit, not a loss.
saying these in an interview costs you the question
- Per-component packages are required for tree-shaking to work.
- Independent versions per component are always more flexible for consumers.
- A single package always makes every app download every component.
- Tokens, icons and components must all live in one package.
- Mixing component versions on one screen is harmless if each works alone.