Tree Shaking
ApexCharts ships modular entry points so you can import only the chart types and features your application actually uses. A line chart built this way weighs 150.0 KB gzipped against 272.8 KB for the full bundle, a little over half.
import ApexCharts from 'apexcharts' gives you every feature except the nine opt-in ones that 7.0 moved out of the default bundle, and every chart type except raincloud, which 7.1 added as an always-explicit import. Those ten are marked below and each needs one extra import. Tree-shaking beyond that is opt-in and nothing else changed, so if you are already importing from apexcharts and use none of the ten, there is nothing to do.
How It Works
ApexCharts uses a registry-based architecture. The core library ships without any chart renderer. Chart-type entry points and feature entry points call ApexCharts.use() and ApexCharts.registerFeatures() respectively to register only what you import.
// Minimal custom bundle — only what you need
import ApexCharts from 'apexcharts/core'
import 'apexcharts/line' // registers: line, area, scatter, bubble, rangeArea
import 'apexcharts/features/legend' // optional legend UI
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
Chart-type and feature entry points are side-effecting: importing one registers what it carries on the shared ApexCharts class. That is why import 'apexcharts/line' binds no name and why you never call ApexCharts.use() yourself.
What It Saves
| What you import | Gzip |
|---|---|
from 'apexcharts' (the default: every type but raincloud, every feature but the nine opt-in ones) | 272.8 KB |
apexcharts/core alone (no chart types) | 139.5 KB |
core + line | 150.0 KB |
core + bar + legend | 166.6 KB |
core + line + legend + toolbar + exports | 177.8 KB |
Measured on apexcharts 7.4.0: each entry bundled with esbuild --bundle --minify --format=iife --target=es2018, then gzip -9. Your own figures will differ a little with a different bundler, target, or compression level; the ratios hold. The per-entry-point costs in the tables below are measured the same way, as the increase over apexcharts/core on its own.
The full bundle is still well below 6.10.0's 291.7 KB, because nine features left it in 7.0. It grew about 12 KB in 7.1, when streamgraph, waterfall and dumbbell joined it. The floor moved the same way, by about 4 KB, since the option trees and presets for the new types live in core whether or not you draw one. It grew about 4 KB more across 7.2 to 7.4, most of it in features/weave, which nearly doubled as the plugin contract went from v1 to v5.
Note that apexcharts/core is the floor, not zero. It carries the scales, axes, grid, data parsing, SVG layer, tooltip, and animation engine that every chart type draws through, so the saving comes from the types and features you leave out, not from core itself.
Chart-Type Entry Points
Import the entry point that matches the chart.type you use. One entry point often registers several related types, because they share a renderer:
| Import | Registers | Adds to core |
|---|---|---|
apexcharts/line | line, area, scatter, bubble, rangeArea | +10.6 KB |
apexcharts/area | Alias for apexcharts/line, same five types | +10.6 KB |
apexcharts/scatter | Alias for apexcharts/line, same five types | +10.6 KB |
apexcharts/bubble | Alias for apexcharts/line, same five types | +10.6 KB |
apexcharts/rangeArea | Alias for apexcharts/line, same five types | +10.6 KB |
apexcharts/bar | bar, column, rangeBar | +17.5 KB |
apexcharts/column | Alias for apexcharts/bar, same three types | +17.5 KB |
apexcharts/rangeBar | Alias for apexcharts/bar, same three types | +17.5 KB |
apexcharts/streamgraph | streamgraph, plus everything apexcharts/line registers. A streamgraph band draws through the range-area renderer, so this entry point carries that renderer and the baseline arithmetic together | +14.7 KB |
apexcharts/waterfall | waterfall, plus everything apexcharts/bar registers. A waterfall bar draws through the range-column renderer, so this entry point carries that renderer, the accumulation and the connectors | +18.7 KB |
apexcharts/dumbbell | dumbbell, plus everything apexcharts/bar registers. A dumbbell draws through the range-bar renderer, so this entry point carries that renderer and the endpoint merge | +18.3 KB |
apexcharts/histogram | Everything apexcharts/bar registers, plus the stats feature. histogram draws through the bar renderer and cannot bin its sample without stats, so this entry point carries both | +20.7 KB |
apexcharts/candlestick | candlestick, boxPlot | +16.9 KB |
apexcharts/boxPlot | Alias for apexcharts/candlestick, both types | +16.9 KB |
apexcharts/violin | violin | +18.3 KB |
apexcharts/raincloud | raincloud , plus violin. A raincloud draws through the violin renderer, so this entry point carries that renderer and the statistics transform. Not in the default bundle | +19.5 KB |
apexcharts/pie | pie, donut, polarArea | +7.9 KB |
apexcharts/donut | Alias for apexcharts/pie, same three types | +7.9 KB |
apexcharts/polarArea | Alias for apexcharts/pie, same three types | +7.9 KB |
apexcharts/radialBar | radialBar | +11.7 KB |
apexcharts/radar | radar | +3.2 KB |
apexcharts/heatmap | heatmap | +2.8 KB |
apexcharts/treemap | treemap | +10.0 KB |
apexcharts/sunburst | sunburst | +5.3 KB |
apexcharts/unit | unit | +14.7 KB |
Types that render through another type's engine. A few chart.type values are presets over a base renderer, so the entry point you import is the base one: funnel and pyramid need apexcharts/bar, gauge needs apexcharts/radialBar, and waffle needs apexcharts/unit. histogram, streamgraph, waterfall, dumbbell and raincloud are the same idea, but each also needs a feature module on top of its base renderer, which is why each has its own entry point above.
Unit shapes. The shape pack for the unit chart's layout: 'custom' is a separate entry point with ordinary named exports rather than a side-effecting registration:
import ApexCharts from 'apexcharts/core'
import 'apexcharts/unit'
import { heart } from 'apexcharts/unit-shapes'
// plotOptions: { unit: { layout: 'custom', positions: heart } }
Shapes tree-shake individually: one shape adds about 3.7 KB on top of apexcharts/unit, importing all of them adds 10.8 KB.
Server rendering. apexcharts/ssr and apexcharts/client are separate entry points with their own API, covered in Server-Side Rendering.
Feature Entry Points
Optional features like the legend, toolbar, and exports are also tree-shakeable. Import only the features you need. Tooltip is always part of core and does not need to be imported separately.
| Import | Feature | Adds to core |
|---|---|---|
apexcharts/features/legend | Legend UI and series toggling | +9.6 KB |
apexcharts/features/toolbar | Toolbar and zoom/pan controls (registered together, both are required for zoom and pan to work) | +13.9 KB |
apexcharts/features/exports | SVG, PNG, CSV, and JSON export | +4.4 KB |
apexcharts/features/annotations | Point, line, and area annotations | +4.8 KB |
apexcharts/features/keyboard | Keyboard navigation (accessibility) | +4.2 KB |
apexcharts/features/drilldown | Click-to-drill navigation with breadcrumb trail | +5.1 KB |
apexcharts/features/morph | Cross-type morph animation when updateOptions changes chart.type | +8.3 KB |
apexcharts/features/stats | Binning and summary statistics from raw observations: required by histogram, and optional for boxPlot and violin, which otherwise expect a precomputed summary or density | +3.5 KB |
apexcharts/features/streamgraph | The wiggle baseline, band ordering and in-band labels for chart.type: 'streamgraph'. Needs a line/area renderer alongside it | +4.6 KB |
apexcharts/features/waterfall | The delta-to-running-total accumulation and the connectors for chart.type: 'waterfall'. Needs a bar renderer alongside it | +1.6 KB |
apexcharts/features/dumbbell | The endpoint merge for chart.type: 'dumbbell'. Needs a bar renderer alongside it | +1.1 KB |
apexcharts/features/all | All of the above, a convenience import equivalent to the full bundle's feature set | +58.5 KB |
Advanced Feature Entry Points
The advanced features introduced in ApexCharts 6.0 are tree-shakeable too, and since 7.0 most of them are opt-in even in the full bundle.
Read the last column before anything else. Not in default means import ApexCharts from 'apexcharts' does not include it and you need the import in the first column; that is the 7.0 breaking change. Never in default means the same thing without the breaking change: it was never in the bundle, so there is nothing to migrate. The rest are in the default bundle already, and the import only matters if you are hand-assembling from apexcharts/core.
The crown is a separate axis: it marks a plan requirement, not an import. A feature can be crowned, opt-in, both, or neither.
| Import | Feature | Adds to core | In default bundle? |
|---|---|---|---|
apexcharts/features/trellis | Trellis (small multiples) | +25.2 KB | Not in default |
apexcharts/features/raincloud | Raincloud chart type | +1.4 KB | Never in default |
apexcharts/features/storyboard | Storyboard (scrollytelling) (includes Perspectives) | +7.2 KB | Not in default |
apexcharts/features/perspectives | Shareable view state (Perspectives) | +6.0 KB | Not in default |
apexcharts/features/ink | Annotation authoring (Ink) | +5.5 KB | Not in default |
apexcharts/features/renderer-canvas | Canvas renderer (Strata) | +5.4 KB | Not in default |
apexcharts/features/link | Linked views & crossfilter | +4.8 KB | Not in default |
apexcharts/features/measure | Measure ruler | +4.0 KB | Not in default |
apexcharts/features/history | Undo / redo (Rewind) | +2.6 KB | Not in default |
apexcharts/features/context-menu | Context menu (Radial Actions) | +1.7 KB | Not in default |
apexcharts/features/weave | Plugin platform (Weave) | +4.1 KB | Included |
apexcharts/features/marks | Custom series types (Marks) | +1.3 KB | Included |
apexcharts/features/facet | Design tokens & OS-aware themes (Facet) | +0.5 KB | Included |
Storyboard's beats are Perspectives tokens, so features/storyboard pulls features/perspectives in with it. That is why its 7.1 KB is barely more than the 6.0 KB Perspectives costs on its own, and why importing both is no more expensive than importing Storyboard alone.
Nothing fails silently. If a feature's configuration is present but the feature is not, ApexCharts warns in the console and names both the bundler import and the script tag. Where a chart can still draw without it, it does and says what it did instead: a trellis renders as a single chart, and renderer: 'canvas' falls back to SVG.
Premium features. The crowned rows are available on the Premium plan and above, as are the two crowned chart types in the table above: unit, which waffle also renders through, and raincloud, added in 7.1. They ship in the same apexcharts package, so the crown marks a plan requirement, not a separate install or a runtime key. Weave, Strata, Marks, and Facet carry no such requirement, and neither does any other chart type.
Always on, no import needed. Some 6.0 capabilities live in core and have no feature entry point: pluggable easing (Cadence), real-time streaming, coherent data transitions, and mobile gestures (Momentum). Do not try to import apexcharts/features/streaming (or cadence / momentum), those entry points do not exist.
Example: Line Chart with Legend Only
import ApexCharts from 'apexcharts/core'
import 'apexcharts/line'
import 'apexcharts/features/legend'
const chart = new ApexCharts(document.querySelector('#chart'), {
chart: { type: 'line' },
series: [
{ name: 'Revenue', data: [30, 40, 35, 50, 49, 60, 70] },
{ name: 'Costs', data: [20, 25, 28, 35, 40, 45, 50] }
],
xaxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] }
})
chart.render()
Example: Bar Chart with Toolbar and Exports
import ApexCharts from 'apexcharts/core'
import 'apexcharts/bar'
import 'apexcharts/features/toolbar' // also registers zoom/pan
import 'apexcharts/features/exports'
const chart = new ApexCharts(document.querySelector('#chart'), {
chart: { type: 'bar' },
series: [{ name: 'Sales', data: [44, 55, 41, 67, 22, 43] }],
xaxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'] }
})
chart.render()
Example: Multiple Chart Types in One App
import ApexCharts from 'apexcharts/core'
// Only import what your app actually uses
import 'apexcharts/line'
import 'apexcharts/bar'
import 'apexcharts/pie'
// Only the features you need
import 'apexcharts/features/legend'
import 'apexcharts/features/toolbar'
// Now render any of the imported types
const lineChart = new ApexCharts(document.querySelector('#line'), {
chart: { type: 'line' },
series: [{ data: [10, 41, 35, 51, 49, 62, 69] }]
})
const barChart = new ApexCharts(document.querySelector('#bar'), {
chart: { type: 'bar' },
series: [{ data: [44, 55, 57, 56, 61, 58] }]
})
const pieChart = new ApexCharts(document.querySelector('#pie'), {
chart: { type: 'pie' },
series: [44, 55, 41, 17]
})
lineChart.render()
barChart.render()
pieChart.render()
Full Bundle (Default Behaviour)
If you import from apexcharts directly (no sub-path), you get every feature except the nine opt-in ones marked above, and every chart type except raincloud.
// Full bundle: every chart type but raincloud, every feature but the nine opt-in ones
import ApexCharts from 'apexcharts'
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
Adding one back is a single side-effecting import next to it, and the two compose: the add-on resolves against the same core the full bundle already loaded, so you pay for the feature and not for a second copy of the library.
import ApexCharts from 'apexcharts'
import 'apexcharts/features/trellis'
Upgrading from 6.x, where all nine were included, is covered in the v7 migration guide.
Adding a Type of Your Own
Every built-in type and every feature already has a sub-path entry point, so there is nothing to register by hand: the imports above are the supported way in, and they are the only way that keeps a slim bundle slim.
For a type ApexCharts does not ship, use Marks. You write a renderItem function that draws one datum and register it under a name of your own, which then behaves like a built-in:
import ApexCharts from 'apexcharts/core'
import 'apexcharts/features/marks'
ApexCharts.registerSeriesType('lollipop', {
renderItem(ctx) {
const { x, y, scales, api, color } = ctx
api.line({ x1: x, y1: scales.y(0), x2: x, y2: y, stroke: color, width: 2 })
api.circle({ cx: x, cy: y, r: 6, fill: color })
},
})
The lower-level ApexCharts.use() and ApexCharts.registerFeatures() are what the entry points above call internally. Both take an object keyed by name, never an array: ApexCharts.use({ line: Line, area: Line }) registers the types line and area, while passing an array registers the keys "0" and "1" and rendering then fails with chart type "line" is not registered.
Do not reach into apexcharts/src/... to get those constructors. Raw source bypasses the shared-module contract that apexcharts/core and the sub-path builds are compiled against, so your bundle ends up with a second copy of Graphics, Fill, Animations, and everything else they share. Measured on 7.4.0, core plus a referenced src/charts/Line.js is 173 KB gzipped against 150 KB for core plus apexcharts/line, and core plus src/modules/legend/Legend.js is 179 KB against 149 KB for core plus apexcharts/features/legend. It costs size rather than saving it, and the gap has widened since 6.10.0.
A deep import that is never referenced looks free, and is not: import 'apexcharts/src/charts/Line.js' on its own has no side effects, so a bundler drops it and the type is simply never registered. The chart then fails at render with chart type "line" is not registered, which reads like a bug in the library rather than a consequence of the import.