Pinned Versions
Pinned Versions
Pinned versions specify exact dependency versions without allowing ranges. Instead of ^1.2.3 accepting compatible updates, a pinned version 1.2.3 accepts only that exact release. Pinning maximizes reproducibility and control at the cost of manual update management.
What Are Pinned Versions
Pinned versions are dependency specifications using exact version numbers. They appear in package.json without range operators: “dependency”: “1.2.3”. Only version 1.2.3 satisfies this dependency. Any other version, even 1.2.4 with a minor bug fix, does not match.
Pinning represents the most conservative dependency management approach. It ensures complete control over dependency versions but requires explicit updates for every version change. Organizations with strict change control often prefer pinning.
How Pinned Versions Work
Pinning affects both how dependencies resolve and how updates are managed. Understanding these implications helps teams decide when pinning is appropriate.
Resolution with pinned versions is deterministic. The specified version is either available or not. There is no range to resolve, no newer compatible version to consider. This simplifies dependency resolution but does not eliminate it when transitive dependencies have ranges.
Updates require explicit action. Unlike ranges where npm update installs newer matching versions, pinned dependencies never update automatically. Each update requires changing the version in package.json. This can be done manually or through tools like Dependabot.
Transitive dependencies may not be pinned. Even with pinned direct dependencies, those packages have their own dependencies with ranges. Lockfiles address this gap, pinning the entire dependency tree.
Consumer experience differs based on how they install. If the design system pins its dependencies, consumers receive those exact versions (assuming they do not conflict with other requirements). This provides predictability but may prevent consumers from receiving updates they want.
Key Considerations
- Pinning increases maintenance burden for updates
- Lockfiles provide pinning benefits without package.json complexity
- Consider pinning for production dependencies, ranges for development
- Automated update tools help manage pinned version updates
- Consumer projects may have different pinning preferences
Common Questions
When should design systems pin dependency versions?
Pinning decisions depend on stability requirements, update discipline, and consumer impact. Different contexts warrant different approaches.
Production dependencies affecting consumers warrant consideration. If the design system’s behavior depends on specific dependency behavior, pinning ensures consistency. However, pinning also means consumers do not receive security fixes automatically.
Critical infrastructure dependencies may warrant pinning. Build tools, transpilers, and bundlers directly affecting package output might be pinned to ensure reproducible builds.
Development dependencies rarely need pinning. Test frameworks, linters, and documentation tools do not affect published packages. Ranges allow receiving updates without manual intervention.
Lockfiles may suffice instead of pinning. package-lock.json or yarn.lock pins resolved versions for development without cluttering package.json with exact versions. This provides reproducibility benefits while keeping dependency specifications clean.
How do consumers handle design systems with pinned dependencies?
Consumer projects inherit dependency choices when installing design system packages. Pinned dependencies in design systems create specific consumer experiences.
Resolution attempts to satisfy all requirements. If the design system pins dependency A at 1.2.3 and the consumer requires A at 1.2.4, npm attempts to resolve this. Multiple versions may be installed if possible, or resolution may fail.
Potential for duplicate packages exists. If different packages require different versions of the same dependency, npm may install both. This increases bundle size and can cause issues with packages expecting singletons.
Consumer preferences may conflict. If consumers want to control their dependency versions, pinned dependencies in design systems reduce their flexibility. Clear documentation of pinned versions helps consumers understand what they are inheriting.
Peer dependencies provide an alternative. Rather than pinning, using peer dependencies lets consumers control versions while design systems specify compatible ranges. This may better serve consumer needs.
Summary
Pinned versions specify exact dependency versions for maximum reproducibility and control. Pinning increases update maintenance burden but ensures precise dependency control. Lockfiles provide similar benefits without package.json complexity. The decision to pin depends on stability requirements and consumer impact considerations.
Buoy scans your codebase for design system inconsistencies before they ship
Detect Design Drift Free