Chart.js v3 tree-shaking removes chart controllers in production builds
0 reputation · 13 Jul 2021, 05:24 UTC
0 reputation · 13 Jul 2021, 05:24 UTC
A Chart.js v3 configuration that renders correctly when loaded via a full UMD bundle in development can fail after a production build with tree-shaking enabled. The ES module entry point does not automatically export or register controllers, elements, scales, or plugins; each must be explicitly imported and registered with Chart.register(). Bundlers such as Webpack, Rollup, or Vite may drop unused exports, leading to runtime errors like Chart.controllers.line is not a constructor or an empty canvas.
The registration API is version-specific and documented in the Chart.js v3 migration guide. Tree-shaking behavior differs across bundler configurations and sideEffects declarations in package.json. Using the CDN UMD bundle avoids the issue but increases payload size. Future releases may change the registration surface.
sideEffects field in chart.js/package.json reliably preserve required controllers, or must consumers list every controller, element, scale, and plugin explicitly?35275 reputation · 13 Jul 2021, 14:07 UTC
The production failure is expected behavior in Chart.js v3, not a bundler defect. The main ES module entry point (chart.js) intentionally omits controllers, elements, scales, and plugins so that bundlers can tree-shake unused code. A UMD script tag registers everything globally, but an ES module import only includes what you explicitly reference. When the LineController is absent, the runtime throws Chart.controllers.line is not a constructor or renders an empty canvas.
Confirmed: Chart.js v3 introduced a modular architecture; Chart.register() is the documented API for adding components; the chart.js/auto entry point imports and registers all built-ins.
Likely: Your Webpack, Rollup, or Vite production configuration is correctly eliminating the controller code because it was never imported. The error is a symptom of missing registration, not a version mismatch.
Uncertain: The exact sideEffects behavior can vary with bundler version and configuration, and future Chart.js releases may adjust the registration surface. Treat any assumption about implicit preservation as unverified.
To render a line chart across Webpack 5, Rollup, and Vite without disabling tree-shaking, import the core and the specific components, then register them before creating the chart:
import {
Chart,
LineController,
LineElement,
PointElement,
LinearScale,
CategoryScale
} from 'chart.js';
Chart.register(
LineController,
LineElement,
PointElement,
LinearScale,
CategoryScale
);
// then create your chart as usual
This set is sufficient for a basic line chart with linear and category axes. If you rely on the built-in tooltip or legend plugins, those must also be imported from chart.js and passed to Chart.register(); omitting them changes the required import list.
If bundle size is not a primary concern, replace the import source with chart.js/auto:
import Chart from 'chart.js/auto';
This mimics UMD behavior by registering all built-in components, but it forfeits tree-shaking benefits and increases payload size.
LineController or related identifiers to verify the code is present.chart.js/auto to quantify the trade-off.Do you use the built-in tooltip or legend plugins? If yes, they must be imported and registered alongside the controllers and scales above; if not, the minimal set is complete.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.