✨ Strapi MCP is now Generally Available - let your agents manage your Strapi content ✨

Ecosystem16 min read

Best Chart Libraries for Developers in 2026

March 31, 2025Updated on September 14, 2026
Top Chart Libraries

This guide compares eight JavaScript chart libraries on renderer, bundle size, licensing, current version, framework wrappers, and accessibility: Chart.js, D3.js, Apache ECharts, ApexCharts, Plotly.js, Highcharts, Nivo, and Recharts, with shorter notes on uPlot, Observable Plot, and visx. The last section shows how to feed any of them from a Strapi 5 backend. It is written for full-stack and frontend developers building dashboards in React, Next.js, Vue, or Angular.

If you choose a chart library from its demo gallery alone, license terms, bundle weight, or screen-reader gaps may surface only after the dashboard ships. All of those are checkable before you write any code. The renderer (Scalable Vector Graphics (SVG), Canvas, or Web Graphics Library (WebGL)) caps how many points a chart can animate and whether assistive technology can read it; bundle size decides whether the chart or the rest of the page loads first; the license decides whether legal joins the meeting.

In Brief

  • Peer-reviewed benchmarks put the interactive ceiling for SVG graph visualizations at roughly 2,000 nodes, Canvas at 3,000 to 5,000, and WebGL at 7,000; Canvas output is invisible to screen readers without developer-added text.
  • Full Plotly.js is about 1.4 MB gzipped, while a minimal ECharts build is roughly 135 KB.
  • Chart.js, Recharts, and Plotly.js (MIT), ECharts (Apache-2.0), and D3 (ISC) permit commercial use; Highcharts charges $185 per developer seat per year for any organizational use.
  • Strapi 5 returns flat JSON (data.title, not data.attributes.title), which can be transformed into the labels/datasets or options/series shapes chart libraries expect; GraphQL needs a plugin install.

Compare Chart Rendering, Performance, and Accessibility

The renderer decides how many elements a library can draw at interactive frame rates and whether a screen reader can find anything inside the chart. SVG provides a Document Object Model (DOM) interface, so every bar and point can carry Accessible Rich Internet Applications (ARIA) attributes and receive its own events.

Canvas paints pixels into a bitmap; it does not expose any drawn objects to the DOM, and nothing inside reaches assistive technology unless you add text alongside. WebGL hands drawing to the graphics processing unit (GPU) and scales furthest, but most browsers cap active WebGL contexts at eight to 16 per page; after that, figures stop rendering.

For an interactive 30 frames per second (FPS) target, Zhao et al., in Springer's Visual Computing (2025), tested D3 and ECharts across renderers on 481 graph datasets. The largest node counts still above 30 FPS were about 2,000 for D3-SVG and ECharts-SVG, 3,000 for ECharts-Canvas, 5,000 for D3-Canvas, and 7,000 for D3-WebGL.

The Counterpoint paper at IEEE VIS 2024 measured frame times of 16 to 607 ms for SVG against 16 to 20 ms for regl-based WebGL on large animated datasets. The IEEE TVCG study by Horak, Kister, and Dachselt put the rough 60 FPS limit at about 10,000 elements for both SVG and Canvas.

Handle the "3 to 9x faster than SVG" result from the SSVG paper in IEEE TVCG carefully: it compares plain SVG against SSVG, a JavaScript translation layer, not native Canvas against SVG.

Sharif et al. (ASSETS '21) found screen-reader users extracted information from web charts with 34% accuracy against 87% for sighted users. Per library, Google Charts (SVG with a tabular representation) scored 73%, D3 (SVG, no table) 17%, and Chart.js (Canvas, relying on developer alt text) 11%. Under WCAG 2.2, charts need text alternatives (1.1.1), cannot rely on color alone (1.4.1), need 3:1 contrast on bars and markers (1.4.11), and must be keyboard-operable (2.1.1). If you pick a Canvas library, budget for a data table or aria-label beside every chart.

Compare the Best JavaScript Chart Libraries

1. Chart.js for Standard Canvas Dashboards

Chart.js is a general-purpose chart library. The current release is Chart.js 4.5.1. The docs' selective-registration example reports removing more than 56 KB of unnecessary code. It renders to Canvas only, with support for drawing in a web worker via OffscreenCanvas. State of JS 2025 ranked it first in Graphics and Animation with 3,045 respondents. The license is MIT.

Registration trips people up. The integration docs state: "Chart.js is tree-shakeable, so it is necessary to import and register the controllers, elements, scales and plugins you are going to use." In react-chartjs-2, typed components register controllers automatically, but scales, elements, and plugins still need explicit registration. ng2-charts uses provideCharts(withDefaultRegisterables()). All three wrappers are current: react-chartjs-2 5.3.1, vue-chartjs 5.3.4, and ng2-charts 10.0.0, with Angular 21 support.

For long time series, the performance docs recommend disabling animation (which enables Path2D caching on line charts) and turning on largest-triangle-three-buckets (LTTB) decimation. The decimation documentation only works on line charts with indexAxis: 'x', a linear or time x-axis, and parsing: false:

// chart-decimation-config.js
const chart = new Chart(ctx, {
  type: 'line',
  data,
  options: {
    animation: false,
    parsing: false,
    indexAxis: 'x',
    plugins: {
      decimation: { enabled: true, algorithm: 'lttb' },
    },
  },
});

2. D3.js for Fully Custom Visualizations

D3.js gives you scales, selections, layouts, and projections rather than chart components, and D3.js 7.9.0 from March 2024 is still current with no version 8 in sight. D3 pulls about 16.6 million downloads weekly under an ISC-style license. D3 is a suite of 30 submodules, so importing d3-array and only the two or three modules you need is normal practice. Types come from the community via DefinitelyTyped.

No official framework wrappers were found in the reviewed sources. In React, the documented pattern is useRef for the DOM node plus useEffect to initialize and clean up. D3 defaults to SVG, but its math layer can support other renderers, which is how Zhao et al. measured it on Canvas and WebGL and why Recharts and visx build on D3 submodules.

3. Apache ECharts for Large Datasets and Maps

Apache ECharts is the library to evaluate when you are plotting hundreds of thousands of points. The current release is ECharts 6.1.0; ECharts 6.0.0 added a chord series and a matrix coordinate system. Governance sits with the Apache Software Foundation under the Apache-2.0 license, and it renders to Canvas by default with an optional SVG renderer.

The online builder produces custom bundles (the handbook cites a pie chart with a title at 135 KB gzipped), or you import from echarts/core and use selective imports:

// echarts-selective-import.js
import * as echarts from 'echarts/core';
import { BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

echarts.use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);

The ComposeOption registration checks flag components you forgot to register.

It helps to treat the headline performance number with care. The ECharts 5 feature page states "rendering within 1s for ten millions of data," a vendor figure from the ECharts 5 era; no equivalent ECharts 6 benchmark exists in official sources, and Zhao et al.'s independent graph test put ECharts-Canvas at 3,000 nodes for 30 FPS. vue-echarts 8.2.0 (maintained by ecomfe, part of the ECharts organization) and echarts-for-react 3.0.6 state ECharts 6 support; ngx-echarts 22.0.0 does not say so explicitly.

4. ApexCharts for Polished Dashboard Defaults

ApexCharts gives you finished-looking defaults out of the box and has jumped two major versions recently. The current release is ApexCharts 7.3.0. ApexCharts 6.0.0 added a plugin platform, hybrid SVG+Canvas rendering, and bundled TypeScript definitions. ApexCharts 7.0.0 moved nine features to opt-in imports, cutting the default bundle by 13.6%. It also added a lean apexcharts/core entry point at 136,921 bytes gzipped, against 267,241 bytes for the default 7.3.0 build.

Colorblind modes (deuteranopia, protanopia, tritanopia, highContrast) arrived in 5.9.0 and WCAG 2.2 Level AA remediation in 5.11.0. Wrappers are current for React (react-apexcharts 2.1.1), Vue 3 (vue3-apexcharts), and Angular (ng-apexcharts 3.0.0). The Vue 2 wrapper last shipped in 2024, and the Svelte wrapper last shipped in 2022.

ApexCharts splits chart options (appearance) from series (values), which suits a content management system (CMS)-backed setup. After a developer defines a Strapi JSON field and frontend code that validates and applies its options, an editor can restyle a chart without a deployment, while an application programming interface (API) route fetches the series data.

5. Plotly.js for Scientific and 3D Charts

Plotly.js covers statistical and 3D plots, and you pay in kilobytes. The current release is Plotly.js 4.1.0 under the MIT license. The dist README lists the main bundle at 4.6 MB minified and 1.4 MB gzipped. Partial bundles help: plotly.js-basic is 397 kB gzipped. Even the smallest partial build is six times Chart.js, so consider lazy-loading it.

Plotly.js 4.0.0 was a breaking release: the scattermapbox, choroplethmapbox, and densitymapbox traces were removed, MathJax 4 is required for LaTeX labels, Node 22 is the minimum, and native TypeScript types shipped for the first time. Version 4.1.0 fixed the declarations for partial bundles.

Plotly uses regl for WebGL on two-dimensional traces such as scattergl; 3D plots still run on the older stack.gl system. The CDN file plotly-latest.js has been frozen at 1.58.5 since July 2021, so load a versioned file like https://cdn.plot.ly/plotly-4.1.0.min.js.

The React wrapper is react-plotly.js 4.1.0; no official maintained Vue or Angular wrapper was found in the reviewed sources.

6. Highcharts for Accessibility and Commercial Support

Highcharts is the commercial option, so compare its license, accessibility, and support terms before evaluating the renderer.

AreaDetails
License and pricingThe EULA 1.0 limits free use to strictly personal, non-commercial, non-professional contexts and explicitly excludes businesses, non-profits, and government bodies. Vendor-listed Highcharts Core pricing is $185 per developer per year or $366 perpetual, with up to six developer seats included and customized pricing for larger teams. Stock, Maps, and Gantt cost extra per seat. Since a May 2026 licensing change, a Dashboards license no longer includes Grid Pro.
Version and exportThe current release is Highcharts 13.0.2. Highcharts 13.0.0 brought palette options, DataTable support, and a gauge redesign; Highcharts 12.6.0 added an experimental contour plot rendered with WebGPU. PNG, JPEG, and SVG export runs client-side by default since 12.3.0; PDF still needs offline-exporting.js.
AccessibilityThe accessibility module is included with every license: keyboard navigation, ARIA roles, screen reader support for JAWS, NVDA, Narrator, VoiceOver, and TalkBack, Windows High Contrast Mode with pattern fills, and chart sonification. The compliance docs reference WCAG 2.2, Section 508, and the European Web Accessibility Directive while leaving final responsibility with you. The only formal conformance report is dated November 2022, covers 11.1.0, and was assessed against WCAG 2.1.
Scale and supportThe Boost module engages at a default threshold of 5,000 points using a stripped-down renderer that bypasses some standard features. Support has service-level agreement (SLA) response times of 36-hour or 17-hour (Advantage and Advantage+).

Calculate seats and add-ons before the evaluation, and ask for a current conformance report if procurement needs one.

7. Nivo for Specialized React Chart Types

Nivo gives you 31 chart types as React components, including Icicle, PolarBar, and Tree. The current release is Nivo 0.99.0 from May 2025, still pre-1.0. Bundled TypeScript declarations ship with the packages, and Nivo 0.98.0 added React 19 support through a react-spring upgrade. Install per chart: npm install @nivo/core @nivo/bar @nivo/pie.

Nivo will not render as a React Server Component. The maintainer closed issue #2626 as not planned for Next.js server-side rendering (SSR): "Since I'm not planning to remove contexts which I use for theming, animations, and tooltips, it does mean that nivo won't support next.js SSR unless it allows context for server components." Every Nivo chart in a Next.js App Router project needs 'use client'.

Maintenance time is limited. The same maintainer wrote in a March 2025 discussion, "it's still maintained, when I can find time for the project." Usage has not slowed, at 30.8 million downloads of @nivo/core in 2025.

8. Recharts for React and shadcn/ui Dashboards

By weekly npm downloads, Recharts is the most-downloaded chart library compared here, at about 40.9 million weekly, more than D3 and Chart.js combined. The current release is Recharts 3.10.1, MIT licensed, and React-only (16.8 through 19), SVG-only, and built on D3 submodules. Generic data typing for data and dataKey props landed in 3.8.0, and Next.js includes recharts among the packages it optimizes by default.

Other JavaScript Chart Libraries for Time Series and Custom React Charts

uPlot (1.6.32, Canvas 2D, about 50 KB minified, MIT) targets high-frequency time series. The author's own 2023 benchmark reports an interactive chart of 166,650 points in 25 ms from cold start. Development has slowed, though the maintainer wrote that "it's not curbed. it's slowed down… it will for sure be maintained for quite a while."

Observable Plot (0.6.17, ISC license) takes a grammar-of-graphics approach: "Plot doesn't have chart types. Instead, it has layered geometric shapes such as bars, dots, and lines." Its latest published release is from February 2025; consider it primarily for exploratory analysis rather than production dashboards. visx (4.0.0, MIT license, from Airbnb) calls itself "not a charting library": low-level React primitives for composing your own, with an @visx/a11y package added in 4.0.0.

Choose a Chart Library for Your Use Case

You can match the library to the constraint that will actually hurt:

  • Standard dashboards and fast setup: Chart.js or ApexCharts. The Chart.js integration fits analytics dashboards and reporting screens that need the standard chart types quickly, and the finance tracker series with Next.js, Strapi, and Chart.js walks through that stack end to end. ApexCharts fits SaaS admin panels where the defaults need to look finished on day one.
  • React or Next.js with shadcn/ui or Tailwind: Recharts. shadcn/ui's chart components are built on Recharts as copy-in source code ("We do not wrap Recharts"), installed with pnpm dlx shadcn@latest add chart and updated to Recharts 3 in March 2026. If your project already uses Tailwind libraries and shadcn, this is the shortest path to a themed dashboard; the Strapi tutorial on building a banking dashboard with Strapi 5 and Next.js 16 uses Recharts for that reason.
  • Specialized React chart types (Sankey, chord, swarm) with no React Server Component requirement: Nivo. It fits specialized React chart types when server-rendered charts are not a requirement.
  • 100K+ data points or built-in geographic maps: Apache ECharts, as a custom build. It fits monitoring dashboards, built-in geographic views, and any screen where data volume, not bundle weight, is the constraint. The post on performance mistakes in Strapi and Next.js apps covers the frontend side of that budget.
  • Scientific, statistical, or 3D plots, or a Python-to-JavaScript pipeline: Plotly.js, lazy-loaded. Plotly earns its weight when your team already builds figures in Python with plotly.py and wants the same charts in production JavaScript, or when you need surface and mesh3d plots. For standard business charts it is hard to justify.
  • WCAG 2.2, Section 508, or SLA-backed support as procurement requirements: Highcharts, after pricing seats and add-ons.
  • A chart type nobody has built yet: D3.js or visx. D3 fits when you need a custom Sankey, a bespoke network layout, or a data-journalism piece where every pixel is designed.

Highcharts is the licensing outlier in this comparison: the Highcharts EULA excludes non-profits and government use from the free-use category, which teams might otherwise interpret as covering all non-commercial projects.

It helps to be skeptical of benchmarks. No independent, non-vendor benchmark covers all of these libraries under one reproducible protocol with recent data. The most cited suite, ChartBench, is published by SciChart, a commercial vendor competing with the libraries it tests, and it runs extreme workloads with high-performance modes most dashboards never turn on.

The uPlot bench directory is the closest community harness but dates to March 2023. Consider running your own dataset through two finalists on your target browser and hardware before deciding.

Connect a Chart Library to Strapi 5

Model Chart Data in Strapi

In a headless setup, Strapi owns the data model and the API, the frontend owns rendering, and caching and edge delivery belong to your hosting platform or CDN. After a developer defines the content model and an administrator grants the appropriate Admin Panel permissions, your content team can update the numbers behind a chart without waiting for a developer. The post on headless architecture covers the split if it is new to you.

Start with the data model. The Content-Type Builder is available in every edition (development environment only) and offers Number fields as integer, big integer, decimal, or float, plus Date, DateTime, Enumeration, and JSON types. Fields marked private are excluded from API responses automatically. A MonthlySale Collection Type with month (date) and revenue (decimal) is enough for a line chart, and the content modeling post covers structuring it for reuse.

Fetch and Transform REST Data

Strapi generates REST API routes for each Content-Type by default, but client access requires suitable roles and permissions, authentication, or another authorization approach. You can request only the fields the chart needs using REST API parameters:

GET /api/monthly-sales?fields[0]=month&fields[1]=revenue&sort=month:asc&pagination[pageSize]=100

Field selection returns string, date, and number attributes. Relations, media, and components need populate, and the REST API does not populate relations unless asked. Pagination defaults to 25 entries per page, so set pageSize or switch to pagination[start]/pagination[limit] for longer series. REST filters such as filters[month][$between] narrow the range server-side. The guide on populate and filtering goes deeper.

Strapi 5 flattened the response format: attributes sit directly on each entry (data[i].month), not under data[i].attributes, and documentId replaces id as the unique identifier. Transform code copied from a Strapi 4 tutorial breaks here. The post on Strapi 5 developer experience explains the change. You can do the reshaping in a server-side route so the browser receives chart-ready JSON:

// lib/chart-data.js
const res = await fetch(
  `${process.env.STRAPI_URL}/api/monthly-sales?fields[0]=month&fields[1]=revenue&sort=month:asc&pagination[pageSize]=100`
);
const { data } = await res.json();

// Strapi 5: flat entries, no data.attributes nesting
export const chartData = {
  labels: data.map((row) => row.month),
  datasets: [{ label: 'Revenue', data: data.map((row) => row.revenue) }],
};

You can swap the shape for options/series (ApexCharts) or series[].data (ECharts) as needed; the Strapi API fetch guide covers the request side.

Configure GraphQL and Webhooks

GraphQL is not on by default. To use it, install the GraphQL plugin with npm install @strapi/plugin-graphql. It exposes a sandbox at /graphql (disabled in production), and you should set depthLimit and maxLimit in config/plugins before shipping, since both are unbounded out of the box. Apollo Client users normalize the cache on documentId, not id. The comparison of REST and GraphQL in Strapi 5 weighs the two for this kind of workload.

For dashboards that refresh on publish rather than in real time, core webhook events such as entry.publish, entry.update, and the other core entry and media events are available in every edition, but a developer must create and configure a webhook endpoint before Strapi sends matching requests. The releases.publish event needs a Growth or Enterprise plan. You can point the configured webhook at a Next.js route that verifies the request and calls revalidateTag to get incremental static regeneration (ISR) with current data; the ISR with Strapi guide shows the wiring.

Handle Client-Only Rendering and TypeScript

Server rendering is the other snag. For browser-dependent chart libraries, you can use next/dynamic with ssr: false inside a Client Component in Next.js App Router, wrap the chart in the Nuxt ClientOnly component in Nuxt, and initialize inside the Angular afterNextRender hook in Angular. The same dynamic import lazy-loads the bundle, which matters most for Plotly.js and full ECharts.

If you run Strapi with TypeScript support (opt-in via npx create-strapi-app@latest my-project --typescript), npm run strapi ts:generate-types produces typings for your Content-Types, though there is no official way yet to share them with the frontend. ApexCharts (since version 6), Plotly.js (since version 4), Recharts, and ECharts ship their own types, so the mismatch to catch is between your API response and the chart's expected data shape. The post on benefits of TypeScript makes the case for setting this up early.

Prototype Two Finalists With Your Real Dataset

Prototype one representative chart with two finalists, using your real dataset and target browser. The finance tracker series provides a working Chart.js example. Strapi's open-source edition includes role-based access control and the Media Library with no software license fee; self-hosted database, hosting, and infrastructure costs still depend on your deployment.

Paul BratslavskyDeveloper Advocate

Related Posts

TutorialsAdvanced·31 min read

Build a Finance Tracker with Next.js, Strapi, and Chartjs: Part 1

Part 1: Set up Strapi and App CRUD functionalities.

·July 30, 2024
 Top 5 best UI libraries to Use in your Next Project
EcosystemBeginner·13 min read

Top 5 best UI libraries to Use in your Next Project

Discover the top 5 UI libraries for creating stunning web application interfaces, perfect for your next project.

·July 1, 2024
HTMX Vs React
Beginner·11 min read

HTMX Vs. React: Comparing Both Libraries

In this article, you'll learn about HTMX, how it works, its strength, and how it compares to React.

·June 7, 2024