question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Feature] RFC: Peer dependencies w/ defaults

See original GitHub issue

Describe the user story

Various packages want to improve the user experience by including most of the packages that would typically be expected from the top-level (think next or create-react-app, for example, which don’t want their users to have to list webpack in their dependencies).

The problem then becomes: what happens to the top-level packages that happen to have peer dependencies on the packages embed within the source package? For example, @zeit/next-css is a package that the end user has to list at the top level, in their own dependencies, but it also has a peer dependency on webpack (through mini-css-extract-plugin).

In most package managers, if the user doesn’t list webpack in their dependencies, the webpack from next will likely be hoisted to the top-level, so mini-css-extract-plugin will likely be able to access it. However, this is incorrect: since the user doesn’t provide any version of webpack themselves, there is no safe way to satisfy the peer dependency.

More than just a theoretical issue, it may cause practical issues: if the user has two workspaces, with one depending on Gatsby and another on Next (or, more generally, if multiple workspaces use different versions of Webpack in any way), there’s no telling which version of webpack will be hoisted - and thus mini-css-extract-plugin may end up using a different version than the Webpack server used by next.

At the same time, end users can’t list webpack in their dependencies either, because it will likely resolve to a different version than the one used by next (even if the ranges are assumed to resolve to the same version if they overlap, the end user still has to keep the ranges in sync, and that’s likely to break at some point).

Describe the solution you’d like

I believe this problem is solvable if we introduce a concept of “Peer dependencies with defaults” - in line with the “Optional peer dependencies” we introduced a year ago. Peer dependencies with default would be defined by using the existing fields:

{
  "dependencies": {
    "webpack": "^4"
  },
  "peerDependencies": {
    "webpack": "^4"
  }
}

So for example, next would have not only a regular dependency on webpack, but also a peer dependency. This pattern, currently invalid because without any semantic meaning, would be defined as such:

A package X listing a package Y as both peer dependency and regular dependency will be guaranteed to access the version of Y provided by its parent if available, or the one listed in its dependencies otherwise.

Going back to the initial story, end users would be able to add webpack to their dependencies when using @zeit/next-css, thus fulfilling the peer dependency. Additionally, because next would list a default peer dependency, it would be guaranteed to use the version provided by its parent, but without requiring it to be provided.

Describe the drawbacks of your solution

This proposal doesn’t have obvious drawbacks - not only does it merely give a semantic meaning to a pattern that didn’t have any, it’s also completely forward compatible: older versions of our package managers will downgrade gracefully by installing the regular dependency and ignoring the peer dependency (without printing any warning).

Describe alternatives you’ve considered

We could try to provide a way for next to directly share its dependencies with its siblings, but I’m worried this would be a very drastic change that would be much more controversial. It would require specific syntax, wouldn’t be forward compatible, and would be technically challenging to get right, if even possible (it would break the assumption that the dependency tree only goes in one direction).

Npm has a proposal to make peer dependencies installed automatically if not provided. Regardless of my general doubts about this approach, I don’t think this would solve the issue described here, as in this case webpack would be resolved independently on the next and @zeit/next-css branches. Even if the package manager was able to ensure they end up resolving to the same version, it wouldn’t necessarily be the same instance as another version of webpack could end up being hoisted to the top level (especially in the multi-workspace setup I described earlier). This isn’t a problem for the proposal here, because the user will explicitly “pick” the version they want to make available to both next and @zeit/next-css, avoiding any hoisting conflict.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:13
  • Comments:15 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
timneutkenscommented, Mar 12, 2020

It’s unlikely that we’ll adopt this for Next.js as webpack is an implementation detail and could be swapped out eventually. The mentioned plugins are deprecated btw as they’re now built into Next.js.

0reactions
merceyzcommented, Jul 16, 2022

Closing as the described solution was implemented in https://github.com/yarnpkg/berry/pull/628 and https://github.com/yarnpkg/berry/pull/2915

Read more comments on GitHub >

github_iconTop Results From Across the Web

RFC 1334 - PPP Authentication Protocols - IETF Datatracker
Network Working Group B. Lloyd Request for Comments: 1334 L&A W. Simpson Daydreamer October 1992 PPP Authentication Protocols Status of this Memo This...
Read more >
RFC 9113: HTTP/2
This specification describes an optimized expression of the semantics of the Hypertext Transfer Protocol (HTTP), referred to as HTTP version 2 (HTTP/2).
Read more >
Pure mode - HackMD
Pure mode ## Summary This RFC is a proposal to add a new opt-in installation ... Peer dependencies are resolved by npm and...
Read more >
Amazon VPC FAQs
You can use any IPv4 address range, including RFC 1918 or publicly routable IP ranges, ... Q. What IP address ranges are assigned...
Read more >
Domain Name System - Wikipedia
The Domain Name System also specifies the technical functionality of the database service that is at its core. It defines the DNS protocol, ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found