Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Installing d3 pulls in multiple versions of the same d3-* packages #3256

Closed
edmorley opened this issue Jan 29, 2018 · 3 comments
Closed

Installing d3 pulls in multiple versions of the same d3-* packages #3256

edmorley opened this issue Jan 29, 2018 · 3 comments

Comments

@edmorley
Copy link

edmorley commented Jan 29, 2018

STR

  1. mkdir d3-test && cd d3-test
  2. yarn add d3@4.12.2
  3. Inspect yarn.lock to see if any packages installed more than once due to different versions. eg using: grep '^[^ ]' yarn.lock | sed 's/@.*//' | sort | uniq -d

Expected

No duplicate d3 packages of differing versions.

Actual

  • d3-format is installed twice, once at version 1.2.1 and once at 1.2.2. The older version is due to the parent d3 package pinning to an exact version, whereas d3-scale pins to a version range (1).
  • d3-selection is installed twice, once at version 1.2.0 and once at 1.3.0. Similar to above, the older version is due to the d3 package pinning to an exact version, whereas d3-drag, d3-brush, d3-zoom pin to 1 and d3-transition pins to ^1.1.0.

This means potentially two copies of both packages can end up in the webpack build output, bloating the size of the browser bundle.

I was going to suggest changing the d3 package's exact version pinning to use version ranges - however it appears that the status quo is intentional (#3088). It seems that if this design decision is to be kept, then either:

  • the d3 repo needs to be updated regularly for new d3 sub-package releases - perhaps using something like Renovate to simplify the process?
  • the sub packages need to use exact versions as well, rather than ranges (although this will presumably create even more chances of dependencies drifting and not being in sync)

Many thanks :-)

@mbostock
Copy link
Member

mbostock commented Jan 29, 2018

I’ve released d3@4.13.0 which fixes this problem for the last 4.x release (for now). But by the nature of this problem I can’t fix this for previous releases (such as 4.12.2).

I’m not going to pin dependencies in the D3 submodules—that would exacerbate the problem. I do keep this repo updated regularly, but there will always be a small amount of time that passes between updating a submodule and updating this module. (A monorepo would be better here, but I wanted something that could allow separate owners for separate repos.)

I suppose the answer is probably to not pin the dependencies in this repo, although that means that the d3 version is essentially meaningless if you are using node_modules rather than the generated UMD bundle. Still, I think that’s the right thing; there’s a variant of this issue that affects ES modules loaded from unpkg, for example.

This loads d3-selection@1.2.0, d3-transition@1.1.1:

https://unpkg.com/d3@4.12.2/index.js?module

But d3-transition@1.1.1 loads d3-selection@^1.1.0:

https://unpkg.com/d3-transition@1.1.1/src/transition/index?module
https://unpkg.com/d3-selection@^1.1.0?module

Which redirects to d3-selection@1.3.0:

https://unpkg.com/d3-selection@1.3.0/index.js?module

That said, when we unpin the D3 dependencies, then loading d3@4.x.y is always equivalent to d3@4 and loads the latest (v4) version of all D3 submodules, since there isn’t any code in the d3 package itself.

Since this is a fairly significant change, unpinning will be part of the 5.0 release.

@edmorley
Copy link
Author

I’ve released d3@4.13.0 which fixes this problem for the last 4.x release (for now). But by the nature of this problem I can’t fix this for previous releases (such as 4.12.2).

Ah great - thank you!

That said, when we unpin the D3 dependencies, then loading d3@4.x.y is always equivalent to d3@4 and loads the latest (v4) version of all D3 submodules, since there isn’t any code in the d3 package itself.

Since this is a fairly significant change, unpinning will be part of the 5.0 release.

Agreed this is a significant change so worth waiting until the major release. Thank you for considering it :-)

If it helps with deciding about tradeoffs, yarn has a resolutions feature that allows for forcing a particular package to be a specific version:
https://yarnpkg.com/lang/en/docs/selective-version-resolutions/

If users needed a particular version of a d3-* package (eg due to wanting to work around a bug accidentally introduced in a point release), then they could use resolutions in their package.json to override any ranges defined by the d3 package. This would be an improvement over the current situation, where d3 can only control the direct dependency versions and not these deeper down the graph.

@will-r
Copy link

will-r commented Dec 23, 2021

I ran into something like this old issue with d3 v7 in a lerna / rollup monorepo. It might be worth recording the solution here.

We seemed to be doing everything right, with careful use of individual d3 modules and only one version of d3-selection present, but still the transition function was not mixed in.

In fact the individual module imports were the problem. We had some views where d3-selection and d3-transition were both imported, but others where we only used d3-selection. If the first import call only pulled in d3-selection then that version would be held by rollup, and any later import of d3-transition would modify a different version of selection that we never saw.

The simple solution was to create a wrapper and ensure that selection was always modified upstream:

import { transition } from 'd3-transition';
import { select, selection } from 'd3-selection';

export {
  transition,
  selection,
  select,
}

Our views import select and transition from this intermediate package, and all is well.

This is not a d3 problem at all but the result of our own overcomplication. All the same, @mbostock, the side-effects of transition are anomalous. Would you consider including an integrated 'selection with transition' package in a later release?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants