Skip to content

Make internal package references strict (or peer dependencies) #8777

@vezaynk

Description

@vezaynk

Provide a general summary of the feature here

I'm running into a recurring issue every time react-spectrum makes a new release, and I'd like to open a thread on whether it's something that can be fixed on your end (or whether it should be mitigated on my end somehow).

Long story short, it's very easy to accidentally install duplicate packages, which breaks type overrides in my monorepo (among other things).

Here's an example from today.

My design system declares all-things-react-aria as peer dependencies, in order to make sure that I don't accidentally end up references multiple versions of react-aria which would produce 2 singletons that don't reference each other. (Turns out this doesn't save us!)

To integrate ReactAria with ReactRouter, I have the following snippet in index.d.ts:

declare module 'react-aria-components' {
  interface RouterConfig {
    href: To;
    routerOptions: NavigateOptions;
  }
}

RouterConfig doesn't actually come directly from react-aria-components. It comes from @react-types/shared (which is declared as a peer dependency of my design system and pinned to "3.31.0" in both my design system and in my monorepo).

Now today, React-spectrum cuts a new release which comes with new versions, including @react-types/[email protected].

Annoyingly, @react-types/[email protected] actually gets pulled into my dependencies because @react-aria/[email protected] (also a new release) expects it, which is in turn installed by [email protected] (which is my current version).

So my node_modules ends up both containing @react-types/[email protected] and @react-types/[email protected] and its a crapshoot on which one gets referenced where.

And all of this is happening because react-aria declares @react-aria/breadcrumbs with a version range

"dependencies": {
    "@react-aria/breadcrumbs": "^3.5.27",

This could be gracefully managed by either

A. making internal dependencies strict (no version range):

"dependencies": {
    "@react-aria/breadcrumbs": "3.5.27",

This will avoid unintended version bumps but does not necessarily guarantee de-duplication.

B. making internal dependencies "peers"

This is my preferred solution, where it will be up to consumers to explicitly declare the version they want to install

"peerDependencies": {
    "@react-aria/breadcrumbs": "^3.5.27",

This will ensure that every package that is intended to be a singleton actually behaves that way.

The best I can do today is to override the behavior via package.json's resolutions field:

"resolutions": {
    "@react-types/shared": "3.31.0"
  },

More importantly, I end up with multiple instances of @react-aria/utils which makes RouterProvider not apply to different copies and breaks my links. Not fun!

This works, but I don't enjoy needing to reach for it.

🤔 Expected Behavior?

I shouldn't end up with duplicate installs.

😯 Current Behavior

Its possible to end up with duplicate installs.

💁 Possible Solution

Make internal package references a peers with a strict (or not strict) version.

🔦 Context

All context already provided

💻 Examples

No response

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions