Packages aren't declaring their dependencies
See original GitHub issueA package should declare its dependencies. E.g. @pixi/sprite
clearly depends on @pixi/display
: import { Bounds, Container } from '@pixi/display';
, but doesn’t declare this in its manifest. Instead, since https://github.com/pixijs/pixijs/pull/8630 even the declaration as peerDependencies
got removed, in favor of a non-standard pixiDependencies
, which no tool in existence will recognize. Note: to me, it should have been a normal dependency to begin with, although there may have been some odd reason, which I missed, why these were peerDependencies
.
While a package manager stuck in bureaucracy and technical debt our friendly default choice npm ignores this (at least last time I checked), such isn’t the case for yarn under strict pnp:
Because the hoisting heuristics aren’t standardized and predictable, PnP operating under strict mode will prevent packages from requiring dependencies that are not explicitly listed; even if other dependencies also depend on it.
This leads to TS not compiling, because it cannot find the related types (imports fail, e.g. Sprite
then misses all properties from DisplayObject
- “Argument of type ‘Sprite’ is not assignable to parameter of type ‘DisplayObject’.”). I didn’t try, but squelching the TS errors would likely lead to a runtime error, where yarn refuses the import on the code.
pixi.js
version: 7.0.0yarn
under strict pnp (though my guess is a “properly” setup pnpm would also error)
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:13 (6 by maintainers)
After reading some of the linked PRs and issues, I’d still choose
dependencies
. I couldn’t see a clear case, where pixi’s setup was at fault1. It’s nice, that you are trying to make things as comfortable as possible for the users, but bending core concepts of the ecosystem might start causing more trouble than good.To me, the relationship still looks as clear. The
dependencies
field was made for package-managers to parse, and form a dependency-graph on the package-level. Fetching and storing the minimal amount of packages, de-duplicating, is their job (primarily, with all the complexity that arises).As already mentioned,
@pixi/sprite
imports code from@pixi/display
, and builds further up from it - the stereotypical plain and simple case fordependencies
. It’s imho not something special like a plugin either, although apeerDependency
would at least tell the package-manager the demand.If you could show a case, where a package-manager duplicates packages for no valid reason, that would be useful. If there is such a case, it might be interesting to analyze (but at least for me, upgrading, and even downgrading, worked without any problems). That would probably be a bug in the related package-manager. I’d understand a temporary work-around, until the issue is fixed, but not abolishing
dependencies
altogether.For the reproduction, I did the simplest possible: no typescript, only yarn and pixi. You’ll need
yarn
somehow though, for the commands. Easiest is having it installed, node’s corepack comes to mind. Perhaps it’s also possible to run the yarn file directly, but I have no experience doing so.As I did not commit the whole yarn cache, a
yarn install
is necessary, to fetch the required packages from npm.https://github.com/ASDFGerte/pixirepro
Running
yarn node index.mjs
will then cause the following error:For a more complex setup, with typescript and all, the problem arises earlier, when typescript cannot resolve the types. This results in errors like:
However, I wanted to keep it as simple as possible.
In case of interest, steps taken to produce that project were:
yarn init -2
.yarn add pixi.js
.index.mjs
with some import to pixi, and change to"type": "module"
in manifest (although the same would happen with cjs).yarn install
after editing the manifest, to get the esm pnp loader.[1]: One got closed by the author, but no statement was made, what the cause or solution was. Another seemed like user-error, where a not yet compatible plugin was installed. Obviously, if there are dependencies on disjoint ranges, multiple versions of pixi will get added, but the fault here lies in telling the package-manager to install packages which aren’t compatible (yet).
Thanks! The issues linked there are much clearer. And yeah, the relationship does make sense since those packages aren’t being used in a fully encapsulated way, but are in some fashion exposed to/tied in with other packages.
Just in case it’s interesting/useful for anyone else: I was curious what could cause an issue in this case, so I took at #8144 since that issue has a clear repro case (checking out https://github.com/yordan-kanchelov/pixi-typescript-boilerplate at 67603fcdbbf4c3ae9513f60179b0620fc66816fd and changing pixijs to
^6.2.2
).@pixi/loaders
andpixi.js/node_modules/@pixi/loaders
).@pixi-spine
packages had a peer dep to pixi packages of^6.1.0
,@pixi/layers
had a peer dep to pixi packages of^6.0.4
, andpixi.js
had regular dependencies to pixi packages of6.2.2
(well,6.5.8
, given I just did the test now where pixijs was set to^6.2.2
, so the newer version ofpixi.js
was validly included according to that rule).pixi.js
with the new version rather than removing the old top-level versions since the new versions are also compatible. I imagine there may be some optimization where it prefers not removing old packages since that may require additional downloads/“unrequired” package updates that aren’t predicted, and it assumes it’s safe sincepixi.js
declares them as true dependencies, so therefore shouldn’t need to interoperate with the versions required as peers by other packagespixi.js
’s dependencies peer dependencies would fix this issue (assuming this would indicate these packages should be provided at the top level in the same way as other packages). However, something interesting I encountered is that if I added a dependency of@pixi/core
of^6.2.2
(another thing which I hypothesized could force the correct versions to be installed, since it would move that package into the top-level scope as opposed to purely being resolved transitively), npm actually failed to resolve entirely due to conflicting peer dependencies. That seems like an npm bug, as it should be able to resolve just fine by top-level package version (and works correctly when you clear the node_modules and package-lock).(Edit: Note that when deduping modules, the way NPM appears to handle the situation is by choosing the first version it encounters. It also appears I was correct that NPM prefers not changing currently installed modules if possible, instead preferring to eschew deduped dependencies when a new package gets installed if the existing dep would need to be updated to be deduped)