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 144.8 KB gzipped against 257 KB for the full bundle, a little over half.
import ApexCharts from 'apexcharts' gives you every chart type and every feature except the nine opt-in ones that 7.0 moved out of the default bundle; those 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 nine, 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, every feature but the nine opt-in ones) | 257.0 KB |
apexcharts/core alone (no chart types) | 134.2 KB |
core + line | 144.8 KB |
core + bar + legend | 159.9 KB |
core + line + legend + toolbar + exports | 172.0 KB |
Measured on apexcharts 7.0.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 13.6% smaller than 6.10.0's, because nine features left it. The floor moved the other way by about 5 KB, so a hand-assembled bundle saves slightly less than it used to against a default that is no longer maximal.
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 | +16.0 KB |
apexcharts/column | Alias for apexcharts/bar, same three types | +16.0 KB |
apexcharts/rangeBar | Alias for apexcharts/bar, same three types | +16.0 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 | +19.3 KB |
apexcharts/candlestick | candlestick, boxPlot | +15.6 KB |
apexcharts/boxPlot | Alias for apexcharts/candlestick, both types | +15.6 KB |
apexcharts/violin | violin | +16.1 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.1 KB |
apexcharts/heatmap | heatmap | +2.3 KB |
apexcharts/treemap | treemap | +10.0 KB |
apexcharts/sunburst | sunburst | +5.3 KB |
apexcharts/unit | unit | +14.8 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 is the same idea, but it also needs the stats feature, which is why it 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.8 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.3 KB |
apexcharts/features/exports | SVG, PNG, CSV, and JSON export | +4.3 KB |
apexcharts/features/annotations | Point, line, and area annotations | +4.6 KB |
apexcharts/features/keyboard | Keyboard navigation (accessibility) | +4.1 KB |
apexcharts/features/drilldown | Click-to-drill navigation with breadcrumb trail | +5.0 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/all | All of the above, a convenience import equivalent to the full bundle's feature set | +50.8 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. 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/storyboard | Storyboard (scrollytelling) (includes Perspectives) | +7.1 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.3 KB | Not in default |
apexcharts/features/link | Linked views & crossfilter | +4.7 KB | Not in default |
apexcharts/features/measure | Measure ruler | +3.9 KB | Not in default |
apexcharts/features/history | Undo / redo (Rewind) | +2.5 KB | Not in default |
apexcharts/features/context-menu | Context menu (Radial Actions) | +1.7 KB | Not in default |
apexcharts/features/weave | Plugin platform (Weave) | +2.4 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 and OEM plans, as is the crowned unit chart type in the table above, which waffle also renders through. 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 chart type and every feature except the nine opt-in ones marked above.
// Full bundle: every chart type, 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.0.0, core plus src/charts/Line.js is 168 KB gzipped against 145 KB for core plus apexcharts/line, and core plus src/modules/legend/Legend.js is 173 KB against 144 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.