Skip to content

sideEffects: false - #2468

Open
mbostock wants to merge 3 commits into
mainfrom
mbostock/side-effects
Open

mbostock wants to merge 3 commits into
mainfrom
mbostock/side-effects

Conversation

@mbostock

Copy link
Copy Markdown
Member

This adds sideEffects: false to our package.json under the rationale that the side effect in question here (the assignment to Mark.prototype.plot to avoid the circular dependency) is entirely internal to Plot, unlike a side effect such as injecting a stylesheet or a global prototype polyfill. The intent of this is to allow esm.sh to bundle Plot more efficiently.

@mbostock
mbostock requested a review from Fil October 30, 2026 16:54
@Fil

Fil commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

This test/bundle-test.js works against main and fails in the PR:

import commonjs from "@rollup/plugin-commonjs";
import {nodeResolve} from "@rollup/plugin-node-resolve";
import {rollup} from "rollup";
import {assert, it} from "vitest";

it("bundled marks have a plot method", async () => {
  const entry = {
    resolveId: (id) => (id === "entry" ? id : null),
    load: (id) => (id === "entry" ? `import {dot} from "./src/index.js"; export default dot().plot;` : null)
  };
  const bundle = await rollup({input: "entry", plugins: [entry, commonjs(), nodeResolve()]});
  const {output} = await bundle.generate({format: "iife", name: "result"});
  assert.strictEqual(new Function(`${output[0].code}; return typeof result;`)(), "function");
});

ref. rollup/rollup#5538 (comment) for a solution that would work for rollup (but maybe not for other bundlers?).

@mbostock

Copy link
Copy Markdown
Member Author

Ugh, stupid bundlers. Thanks for finding.

@mbostock

Copy link
Copy Markdown
Member Author

@mbostock

Copy link
Copy Markdown
Member Author

So somewhat astonishingly, the behavior depends on whether we add @rollup/plugin-node-resolve…

@mbostock

Copy link
Copy Markdown
Member Author

I guess that’s because it only checks for sideEffects: false if you have that plugin enabled.

@mbostock

Copy link
Copy Markdown
Member Author

Your test still doesn’t work because it only imports the dot mark, but not Mark, and hence Rollup thinks that the Mark.prototype.plot assignment is tree-shakable. But I think that’s valid. So I won’t add a test, but I’m going to publish this as a prerelease so we can see what esm.sh does.

@mbostock

mbostock commented Oct 30, 2026 •

Copy link
Copy Markdown
Member Author

I think I’ve fixed it, but now I’m blocked by esm-dev/esm.sh#1490; esm.sh isn’t currently serving new packages due to being out of disk space.

@mbostock

mbostock commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

esm.sh is back, and I’ve confirmed that this technique now works. It does mean that importing a subclass of Mark by itself (such as dot) won’t include the plot method, though. I’m not sure if that’s fixable… or acceptable. But I don’t think I should overindex on the tree shaking behavior of bundlers; more important that the library loads quickly in the common case.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants