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.

Packages aren't declaring their dependencies

See original GitHub issue

A 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.0
  • yarn under strict pnp (though my guess is a “properly” setup pnpm would also error)

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
ASDFGertecommented, Oct 30, 2022

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 for dependencies. It’s imho not something special like a plugin either, although a peerDependency 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:

Error: @pixi/mixin-cache-as-bitmap tried to access @pixi/core, but it isn’t declared in its dependencies; this makes the require call ambiguous and unsound.

For a more complex setup, with typescript and all, the problem arises earlier, when typescript cannot resolve the types. This results in errors like:

Argument of type ‘Sprite’ is not assignable to parameter of type ‘DisplayObject’.

However, I wanted to keep it as simple as possible.

In case of interest, steps taken to produce that project were:

  • Run yarn init -2.
  • Remove unnecessary files editorconfig and README.
  • Change gitignore to exclude yarn cache.
  • Run yarn add pixi.js.
  • Add index.mjs with some import to pixi, and change to "type": "module" in manifest (although the same would happen with cjs).
  • Run 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).

1reaction
luxaritascommented, Nov 16, 2022

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).

  • Indeed, even though pixi was using peer dependencies, there are still duplicate packages (@pixi/loaders and pixi.js/node_modules/@pixi/loaders).
  • The @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, and pixi.js had regular dependencies to pixi packages of 6.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 of pixi.js was validly included according to that rule).
  • It is interesting that npm prefers adding new dependencies under 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 since pixi.js declares them as true dependencies, so therefore shouldn’t need to interoperate with the versions required as peers by other packages
  • I’m wondering if making pixi.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)

Read more comments on GitHub >

github_iconTop Results From Across the Web

npm install not installing dependencies listed in package.json ...
I installed a npm module that I wrote. This module I have tested many times and I can be sure I have declared...
Read more >
30.3 Declaring Dependencies: Depends, Suggests, Imports
The Suggests field can be used to declare dependencies on packages that make your package more useful but are not completely essential.
Read more >
NPM doesn't install module dependencies - Stack Overflow
I found out that two of the packages needed different versions of the dependency. I resolved the conflict, removed node_modules and after a...
Read more >
Package dependencies - Dart programming language
Dependencies are one of the core concepts of the pub package manager. A dependency is another package that your package needs in order...
Read more >
7. Declaring relationships between packages - Debian
This declares an absolute dependency. A package will not be configured unless all of the packages listed in its Depends field have been...
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