This is a fork of plotly/plotly.js maintained at runsascoded/plotly.js.
Provide a customized plotly.js for use across several projects (NJ crashes, PATH ridership, hub-bound travel, hudson-transit, awair, etc.) via pltly (React wrapper) and pds (dependency management).
- ESM conversion: All 971 source files converted from CJS to ES modules.
"type": "module"in package.json. Enables tree-shaking by bundlers. - d3 v7 migration: Replaced
@plotly/d3(vendored d3 v3, 229 KB CJS blob) with modern d3 v7 ESM packages.src/lib/d3-compat.jspolyfills v3 patterns (enter/merge,.style({}),.select()data propagation). - Tree-shakeable factory:
createPlotly()inlib/factory.js— consumers import only traces/components they need. Scatter+bar+legend: 741 KB min (-32% vs upstream basic 1,089 KB). - Dep inlining:
gl-mat4→ inline 4x4 ops, Node.jsevents→ MiniEmitter, shapes decoupled from core - z-order fix: Preserve z-indexed subplots during
relayoutfor correct pan/zoom - Touch fix: Prevent duplicate
plotly_clickand scroll-triggered clicks - Flush legend toggle rects: Expand legend item hit areas so they tile flush (no hover gaps)
- Custom legend symbols:
legendsymbol.pathtrace attribute for custom SVG legend icons - Treemap transpose: Add
tiling.transposeattribute for treemap traces exportsmap: Subpath imports (plotly.js/basic,plotly.js/core, etc.) vialib/- Lite bundle:
plotly.js/lite— scatter + bar with only essential components - Deferred margins:
config.deferAutoMarginfor 15-29% faster first paint - Perf instrumentation:
performance.measure()around key render phases - pnpm: Switched from npm to pnpm (lockfile, overrides, build scripts)
Built files are not tracked on main. dist/ is fully gitignored. Source data files (topojson, schema) live under topojson/dist/ and are generated by the build.
The dist branch is auto-built by GHA (runsascoded/npm-dist@v1) on push to main. It includes ESM source (lib/, src/) for tree-shakeable imports AND pre-built bundles (dist/) for CDN/script-tag use.
# Full local build (all bundles + locales + schema)
pnpm run build
# Individual steps
pnpm run bundle # main plotly.js + plotly.min.js
pnpm run extra-bundles # basic, cartesian, finance, geo, gl2d, gl3d, mapbox
pnpm run fork-bundles # lite, minimal
pnpm run schema dist # generate plot-schema.jsonBuild scripts in tasks/ are .cjs (CJS) or .mjs (ESM). The preprocess step generates src/plotcss.js and lib/*.js entry points — run it before bundling.
| Bundle | Entry point | Unminified | Contents |
|---|---|---|---|
| lite | plotly.js/lite |
1,944 KB | scatter + bar, 6 components |
| minimal | plotly.js/minimal |
2,251 KB | scatter + bar, all 15 components |
| basic | plotly.js/basic |
2,550 KB | scatter + bar + pie + calendars, all components |
pnpm run perf # benchmark minimal bundle
pnpm run perf:lite # benchmark lite bundle
pnpm run perf:basic # benchmark basic bundle
# Options:
node perf/bench.mjs --lite --minify # minified bundle
node perf/bench.mjs --lite --defer # with deferAutoMargin
node perf/bench.mjs --lite --update # accept new bundle size
node perf/bench.mjs --lite --headed # visible browserBundle sizes are asserted at the exact byte level in perf/thresholds.json. Pass --update to accept changes.
plotly.js (this fork, ESM)
└─ pltly (React hooks: hover, solo, pin, fade, dual-axis, theme)
└─ consumer apps (crashes, path, hub-bound, hudson-transit, awair, etc.)
- pltly wraps plotly.js with React hooks for legend interaction, trace highlighting, mobile touch fixes, and theme support
- pds manages switching between local/GH-dist/npm versions across the stack
# In consumer project:
pds l plotly # switch to local ESM source (Vite imports directly, no pre-bundling)
pds gh plotly # switch to GitHub dist branch (ESM source + pre-built bundles)
pds n plotly # switch to upstream npmWith ESM, pds l and pds g behave identically — no more CJS pre-bundling issues, no resolve.alias hacks, no optimizeDeps configuration needed.
The fork is fully ESM. Consumer bundlers (Vite, esbuild) handle plotly natively — no CJS pre-bundling, no plotly.js-dist-min separate package, no Vite optimizeDeps workarounds.
Consumer apps should NOT need to build their own legend UIs, implement trace fading/highlighting, handle mobile touch quirks, or manage plotly bundle loading. These are handled by plotly.js (rendering) and pltly (React integration).
Keep in fork: ESM conversion, custom legend symbols, lite bundle, registration system changes
Consider upstreaming (bug fixes, non-breaking): flush legend toggle rects, z-order relayout fix, touch interaction fixes, deferAutoMargin
Active specs in specs/:
remove-registration-system.md— eliminate global registry, enable full tree-shaking (partially done: factory entry point works, shapes/modebar decoupled, drawing converted to named exports)pltly-factory-migration.md— migrate pltly React wrapper to usecreatePlotly()factory
Completed specs in specs/done/ (15 total):
esm-conversion, esm-cjs-interop, esm-ternary-attrs, esm-css-imports,
stackgl-esm-shim, dist-branch-esm, dist-extra-bundles, dist-branch-missing-dirs,
dist-lib-stale, flush-legend-toggle-rects, legend-icon-symbols,
custom-minimal-bundle, perf-harness, fast-initial-render, d3-v7-migration