Skip to content

[Feature] Singleton packages #417

@arcanis

Description

@arcanis

Describe the user story

My package is a singleton. It must not be present multiple times within my application. How can I do this without using the resolutions field, which doesn't surface the potential version mismatches?

Describe the solution you'd like

Interestingly, this issue isn't necessarily a feature request ... 🙂 I've seen a thread discussing it somewhere, and I thought it could be a useful reference in the future to put my thoughts here.

It would be easy to start by asking whether singletons are needed - I'm sure lots of people have very good arguments why they are useful (and I myself have a few). Still, answering this from the very beginning sounds like going the wrong way to me. Before even answering whether we need singletons, we first should discuss whether they already exist with the tools we have right now. Only once we have figured out what we have we can discuss what we're missing and what we should have.

So - what do we have right now that would be connected to singleton? Peer dependencies. To better understand what I mean, consider the following properties:

  • A peer dependency tells the package manager that, given app → react-foo ⇢ react (with ⇢ being a peer dependency), react should be provided somehow by app. We will use the following notation to keep track: app → react-foo → (app → react).

  • Peer dependencies are nested; so if we also have react-foo → react-bar ⇢ react, it will first be transformed into react-foo → react-bar → (react-foo → react) before being transformed again into react-foo → react-bar → (app → react) (because of the previous point).

And that's very interesting, because it becomes clear that, through peer dependencies, neither react-foo nor react-bar ever used a different version of react than the one provided by app.

So where does that bring us? Singletons are the exact same thing as a package being referenced exclusively through peer dependencies (except for the top-level, of course). If every package depends on react through peer dependencies, there will only ever be one version of it in the dependency tree - and thus one single instance.

We now know that singletons already exist, right now. So the next question we should have is: "is it enough?". And that's an interesting one - why do we have this discussion about singletons in the first place? In my opinion, there are two reasons:

  • People want clear solutions instead of a blog post explaining the intricacies of a dependency tree as I'm basically doing right now. By this I mean: we are doing a bad job explaining how to solve the initial use case.

  • In order for this singleton pattern to be efficient, packages need to list their dependencies properly. For example, a single package relying on react through a regular dependency may cause an additional package to be added in the dependency tree.

So how to solve this? This is, imo, the real question. We don't need a "singleton" feature, because we already have it through peer dependencies (which are a beautiful but complex feature). What we need is a way to help our users understand how to leverage it.

(one particular way I can see that happen would be through the addition of a preferPeer flag which would cause the install to emit a warning unless the dependent package specified a special flag into its peerDependenciesMeta field. When the offending package is the top-level one, this warning would be upgraded into an hard error to better surface the problem to library authors.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    discussionDiscussion about the projectecosystemThis feature affects the whole ecosystemenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions