-
Notifications
You must be signed in to change notification settings - Fork 233
Description
Hi all,
From my understanding Plottable was originally built around UMD/CommonJS patterns. What would be required to introduce first-class ESM support (with proper sideEffects flags and module exports) to enable tree-shaking in modern bundlers like Vite and Webpack 5? Would this require a major refactor of the internal architecture, or could it be introduced incrementally?
The Structural Limitation Today
At present, consumers typically import Plottable as a single namespace:
import * as Plottable from "plottable";This pattern effectively forces bundlers to include the entire exported surface area of the library. Even if a developer only uses a single plot type (for example, Line), the bundler has no reliable way to eliminate unused plot types, scales, interactions, components, and utilities.
Because the package is distributed as a monolithic UMD/CJS bundle, static analysis becomes difficult. Tree-shaking relies on static import graphs. UMD patterns and namespace aggregation obscure that graph.
So I believe modern libraries expose multiple entry points and granular exports. Instead of importing the entire namespace, consumers can import only what they need:
import { Line } from "plottable/plots";
import { Time } from "plottable/scales";
import { Axis } from "plottable/axes";Incremental Migration Path (If a Full Rewrite Is Risky)
A complete architectural rewrite may not be necessary. If one is needed though, it may look like this, convert internal TypeScript modules to ESM syntax while preserving structure, and introducing a parallel ESM build using Rollup or ESBuild.
Maintain dual outputs:
*plottable.cjs.js
*plottable.esm.js
Lastly gradually expose granular export paths. So here's an example rollup config:
export default {
input: "src/index.ts",
output: [
{
file: "dist/plottable.esm.js",
format: "es"
},
{
file: "dist/plottable.cjs.js",
format: "cjs"
}
],
external: ["d3"]
};This allows backward compatibility while progressively enabling modern optimization.
Why This Matters Strategically
In 2026, the viability of a JavaScript library is no longer determined solely by whether it “works.” It increasingly depends on how well it aligns with modern ecosystem expectations. Bundle efficiency, native ESM compatibility, smooth framework integration, and TypeScript-first workflows are now baseline requirements rather than optional enhancements. Even if Plottable remains technically functional and stable, the absence of proper ESM support can create perception challenges.
Developers evaluating charting libraries today often assess factors like tree-shakability, bundle size impact, lazy-loading compatibility, and integration friction with React or Next.js before they even evaluate feature depth. Without modern packaging, Plottable risks being excluded early in technical evaluations — not because of deficiencies in charting capability, but because of ecosystem misalignment.
Performance Implications
The performance implications are practical rather than theoretical. Consider a typical import pattern:
import { Line } from "plottable";Under the current packaging model, a bundler may end up including most of the library, even if only the Line plot is used. Static analysis becomes less effective when the export surface is aggregated and not structured for granular elimination.
With proper ESM support and accurate sideEffects configuration, developers could instead write:
import { Line } from "plottable/plots";In that scenario, only the Line plot and its direct dependencies would be bundled. In real-world dashboards — particularly in enterprise environments where performance budgets matter, this could meaningfully reduce initial JavaScript payload size. Over time, such efficiencies compound across applications and deployment surfaces.
Developer Experience and Modern Patterns
Native ESM support also unlocks more ergonomic development patterns. For example, code splitting and lazy loading become straightforward when modules are exposed granularly:
const LinePlot = React.lazy(() =>
import("plottable/plots/line")
);Without modular export paths, this pattern is difficult or impractical to implement. Beyond performance, this impacts architectural flexibility in modern React and Next.js applications.
These are just some thoughts,
Michael