# Apache ECharts — Administrator & Architect Guide

> Comprehensive operational, architectural, and developer reference for Apache ECharts v6.0.0. Audience: platform engineers embedding ECharts at scale, library authors extending it, build engineers configuring tree-shaken bundles, and security/compliance reviewers.

---

## Executive Summary

**Apache ECharts** is a browser-based charting and data-visualization library, governed by the Apache Software Foundation under the Apache 2.0 license. Version 6.0.0 (commit `c8adaf4`, 2026-02-26) ships **23 chart types**, **28 component types**, **7 coordinate systems**, **dual renderers** (Canvas + SVG), **server-side rendering**, **53 locales**, and **37 built-in themes**.

| Attribute | Value |
|---|---|
| Package | `echarts` |
| Version analyzed | `6.0.0` |
| License | Apache-2.0 |
| Source repo | `apache/echarts` |
| Source commit | `c8adaf4` (2026-02-26) |
| Runtime deps | `zrender@6.0.0`, `tslib@2.3.0` |
| Build tool | Rollup 2.34.2 + esbuild 0.8.39 + Terser 5.x |
| Language | TypeScript 4.4.3 |
| Module system | ESM + UMD + CJS (multi-entry exports) |
| Test framework | Jest 26 (unit) + Puppeteer 23 (visual regression) |
| Source files (.ts) | 1,909 |
| Source size | ~5.49 M characters |
| Bundle entries | `all`, `common`, `simple`, `blank`, `ssr`, `extension` |

ECharts is **library-as-platform**: it does not run a server, does not own data, and does not perform network I/O. All operational concerns concern *embedding* it in a host application — bundle size, render performance, accessibility, SSR hydration, theme governance, and locale loading.

---

## Architecture

### High-level component diagram

```
┌────────────────────────────────────────────────────────────────────────┐
│                            Host Application                            │
│   (React / Vue / Angular / vanilla — provides DOM container & data)    │
└─────────────────────────────────┬──────────────────────────────────────┘
                                  │  init(dom, theme, opts)
                                  ▼
┌────────────────────────────────────────────────────────────────────────┐
│                          ECharts Instance (core)                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌──────────────┐  │
│  │ GlobalModel │  │  Scheduler  │  │  ChartView  │  │ ComponentView│  │
│  │ (option →   │→ │  (pipeline  │→ │  (per-      │  │ (axis, grid, │  │
│  │  models)    │  │   stages)   │  │   series)   │  │  legend, …)  │  │
│  └─────────────┘  └─────────────┘  └─────────────┘  └──────────────┘  │
│         │                │                │                  │        │
│         ▼                ▼                ▼                  ▼        │
│  ┌──────────────────────────────────────────────────────────────────┐  │
│  │                  Coordinate Systems Manager                      │  │
│  │   cartesian (grid) │ polar │ geo │ single │ parallel │ calendar │  │
│  │                          │ matrix (v6 NEW)                       │  │
│  └──────────────────────────────────────────────────────────────────┘  │
│         │                                                              │
│         ▼                                                              │
│  ┌──────────────────────────────────────────────────────────────────┐  │
│  │            Visual Pipeline (visual/, processor/, layout/)        │  │
│  │   data transform → scale → visual mapping → label layout         │  │
│  └──────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────┬──────────────────────────────────────┘
                                  │  render display objects
                                  ▼
┌────────────────────────────────────────────────────────────────────────┐
│                        zrender (graphics engine)                       │
│           ┌─────────────────────┴──────────────────────┐               │
│           ▼                                            ▼               │
│   ┌───────────────┐                            ┌──────────────┐        │
│   │ CanvasPainter │                            │  SVGPainter  │        │
│   │  (default)    │                            │  (a11y / SSR)│        │
│   └───────────────┘                            └──────────────┘        │
└────────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
                   ┌───────────────────────────────┐
                   │    DOM <canvas> / <svg>       │
                   └───────────────────────────────┘
```

### Layered model

ECharts is organized in five distinct layers, each with a clear contract. Files live under `src/`:

| Layer | Folders | Responsibility |
|---|---|---|
| **Core** | `src/core/`, `src/echarts.*.ts` | Lifecycle (`init`, `dispose`), action dispatch, event center, scheduler, plugin registration (`use()`) |
| **Model** | `src/model/`, `src/data/` | `option` → typed models (`GlobalModel`, `SeriesModel`, `ComponentModel`); data store (`SeriesData`, `DataStore`, `Source`) |
| **Coordinate** | `src/coord/` | Map data values → screen coordinates (cartesian, polar, geo, single, parallel, calendar, matrix) |
| **Visual & Layout** | `src/visual/`, `src/processor/`, `src/layout/`, `src/scale/`, `src/label/` | Compute colors, sizes, positions; resolve axis scales; place labels with collision avoidance |
| **View** | `src/view/`, `src/chart/{type}`, `src/component/{type}` | Build display objects, hand off to `zrender` painter |

The flow on every `setOption()` call is strictly one-way: **option → models → coord systems → visual pipeline → views → zrender → painter → DOM**. Data never flows backward; user interaction enters via *actions* dispatched at the core, which mutate models and trigger a new render cycle.

> [!NOTE]
> The one-way data flow is a deliberate architectural constraint. If you are building a custom extension that needs to feed information back from a view to a model, use `dispatchAction` to route through the core — never mutate model state directly from a view.

### Core class hierarchy

Sourced from `_briefing/extracted/class_hierarchy.tsv` (53 classes). Highlights:

| Class | Inherits | Source | Role |
|---|---|---|---|
| `ECharts` | `Eventful` | `src/core/echarts.ts:366` | Top-level instance. Owns Scheduler, GlobalModel, MessageCenter, zr instance. |
| `MessageCenter` | `Eventful` | `src/core/echarts.ts:275` | Pub/sub for chart events (`click`, `legendselectchanged`, …) |
| `Scheduler` | — | `src/core/Scheduler.ts:102` | Pipeline of `Task` nodes; executes per-stream incremental updates |
| `Task` | — | `src/core/task.ts:92` | Single node in the rendering pipeline; supports streaming + dirty regions |
| `CoordinateSystemManager` | — | `src/core/CoordinateSystem.ts:46` | Registers/looks up coord-system creators (cartesian, polar, …) |
| `GlobalModel` | `Model` | `src/model/Global.ts:156` | Root option container; holds all `ComponentModel` and `SeriesModel` instances |
| `Model` | — | `src/model/Model.ts:48` | Generic option-tree wrapper with `get/getModel/getShallow` |
| `ComponentModel` | — | `src/model/Component.ts:53` | Base for axis/grid/legend/tooltip/etc models |
| `SeriesModel` | — | `src/model/Series.ts:129` | Base for every chart-type model; owns one `SeriesData` |
| `OptionManager` | — | `src/model/OptionManager.ts:58` | Merges `option`, `baseOption`, timeline `options[]`, media queries |
| `ChartView` | — | `src/view/Chart.ts:98` | Base class for chart rendering; subclasses override `render()` |
| `ComponentView` | — | `src/view/Component.ts:63` | Base for axis-line, legend, title, etc. views |
| `Axis` | — | `src/coord/Axis.ts:54` | Generic axis (extent + scale + ticks); reused across coord systems |
| `View` | `Transformable` | `src/coord/View.ts:42` | Pan/zoom transform layer used by geo and tree |
| `LabelManager` | — | `src/label/LabelManager.ts:197` | Global label collision/overlap resolution |
| `IntervalScale` | — | `src/scale/Interval.ts:30` | Linear numeric scale with nice ticks |
| `LogScale` | `IntervalScale` | `src/scale/Log.ts:40` | Log10 (base configurable) |
| `OrdinalScale` | `Scale` | `src/scale/Ordinal.ts:45` | Categorical |
| `TimeScale` | `IntervalScale` | `src/scale/Time.ts:113` | Time axis with locale-aware tick formatting |
| `SeriesData` | — | `src/data/SeriesData.ts:151` | Columnar data view backed by `DataStore` |
| `DataStore` | — | `src/data/DataStore.ts:159` | Typed-array-backed columnar storage; supports streaming `appendData` |
| `Graph` | — | `src/data/Graph.ts:32` | Node-link data structure for graph/sankey/chord |
| `Tree` | — | `src/data/Tree.ts:321` | Hierarchical data for tree/treemap/sunburst |

### Render pipeline (Scheduler stages)

The Scheduler (`src/core/Scheduler.ts`) runs an ordered set of stages on every render. Each stage may register tasks via `registerProcessor`, `registerVisual`, or `registerLayout`. The pipeline:

1. **Preprocessor** — normalize raw `option` (legacy migrations live in `src/preprocessor/`)
2. **Statistic / Filter** — `processor/dataFilter.ts`, `processor/dataSample.ts` for downsampling
3. **Visual** — color/size/symbol assignment (`visual/`)
4. **Coordinate system update** — recompute axis extents, ticks, view rects
5. **Layout** — series-specific positioning (bar layout, pie layout, force-directed, …)
6. **Render** — instruct each `ChartView`/`ComponentView` to update display objects
7. **Label layout** — `LabelManager` resolves collisions globally

Tasks are **stream-aware**: large datasets run incrementally across animation frames so the main thread is never blocked for long.

> [!TIP]
> When profiling render performance, look at the Scheduler pipeline in DevTools — each `Task` node corresponds to a discrete render stage. Long-running tasks in the "Visual" or "Layout" stages typically indicate too many data points or overly complex label collision resolution.

### Bundle anatomy

Three pre-built entries are shipped:

| Entry | File | Contents | Size class |
|---|---|---|---|
| `echarts` (all) | `dist/echarts.js`, `dist/echarts.min.js` | Every chart, component, renderer | Largest |
| `echarts/core` + `use()` | `dist/echarts.simple.js` baseline + selective imports | Tree-shakeable; pick what you need | Smallest |
| `echarts/common` | `dist/echarts.common.js` | Common subset (line/bar/pie/scatter + grid/tooltip/legend/...) | Medium |

Build is driven by `build/build.js` (Rollup) and produces UMD (`dist/echarts.js`), ESM (`dist/echarts.esm.mjs`), and minified variants. The `sideEffects` array in `package.json` (lines 33-44 of dependencies.cbf) explicitly marks **only** the entry indexes, theme, i18n, chart, component, and extension modules as side-effecting; everything else is tree-shakable.

### Module reference (top-level src/)

| Folder | Files | Responsibility |
|---|---|---|
| `src/core/` | 9 | Engine: `echarts.ts` (init, instance, MessageCenter), `Scheduler.ts`, `task.ts`, `CoordinateSystem.ts` |
| `src/model/` | 8 | `Global.ts` (root model), `Component.ts`, `Series.ts`, `OptionManager.ts`, `referHelper.ts` (component cross-refs) |
| `src/data/` | 8 | `SeriesData`, `DataStore`, `Source`, `Graph`, `Tree`, `OrdinalMeta`, `DataDiffer` (for animation) |
| `src/chart/` | 23 chart-type folders | Each has a model + view + visual; e.g. `bar/`, `pie/`, `line/`, `treemap/`, `sankey/`, `custom/` |
| `src/component/` | 33 component-type folders | Axis, grid, legend, tooltip, dataZoom (3 variants), visualMap (2 variants), brush, geo, calendar, matrix (NEW v6), thumbnail (NEW v6) |
| `src/coord/` | 12 | One folder per coordinate system: `cartesian/`, `polar/`, `geo/`, `single/`, `parallel/`, `calendar/`, `matrix/`, plus `Axis.ts` and `View.ts` shared base |
| `src/visual/` | 11 | Color, symbol, opacity, decal mappings; `VisualMapping.ts` is the universal applier |
| `src/processor/` | 4 | Data-stage operators: `dataFilter`, `dataSample`, `dataStack`, `dataset`-related |
| `src/layout/` | 3 | Cross-series layout helpers (bar grouping, points-on-line, etc.) |
| `src/scale/` | 8 | `Interval`, `Log`, `Ordinal`, `Time`, `Scale.ts` base, `helper.ts` (ScaleCalculator), `breakImpl.ts` (axisBreak) |
| `src/label/` | 6 | `LabelManager` (collision resolution), `labelLayoutHelper`, `labelGuideHelper` |
| `src/animation/` | 5 | Universal transition, custom-graphic transitions, `AnimationWrap` |
| `src/loading/` | 1 | Default loading spinner used by `showLoading()` |
| `src/preprocessor/` | 1 + helper | Legacy `option` migrations |
| `src/renderer/` | 2 | `installCanvasRenderer`, `installSVGRenderer` |
| `src/theme/` | 1 | Default + dark theme registration |
| `src/i18n/` | 26 | Built-in locale registrations |
| `src/view/` | 2 | `Chart.ts`, `Component.ts` base classes |
| `src/util/` | 24 | Conditional expressions, KDTree (point picking), event processor, model utilities, shape helpers, throttle |
| `src/legacy/` | 2 | Deprecated-shape compatibility shims |
| `src/export/` | 8 + api/ | Public API surface re-exports for `echarts.all.ts`, `.common.ts`, `.simple.ts` |
| `extension-src/bmap/` | 5 | Baidu Maps coordinate system integration |
| `extension-src/dataTool/` | 3 | `gexf` parser, `prepareBoxplotData` quartile helper |
| `ssr/client/src/` | 2 | `hydrate(dom, options)` for SSR-rendered SVG |

### Plugin / extension architecture

ECharts uses a **registration-by-import** model. Every chart, component, renderer, feature, and extension exports an `install` function. The user calls `echarts.use([install1, install2, …])`, which pushes each installer onto a registry consulted during `init()`. Tree-shakers can then prune unused installers.

Cross-repo pattern observation: this `use()` model resembles **Mermaid's plugin API** and **Storybook's addon registration** — a `use()` function that takes an array of installers, each registering capabilities into a global manager. Library authors who already understand those ecosystems can apply the same mental model here.

Built-in installer categories:

| Category | Examples | Source |
|---|---|---|
| Charts | `BarChart`, `LineChart`, `PieChart`, `MapChart`, `CustomChart` | `src/chart/{type}/install.ts` |
| Components | `GridComponent`, `TooltipComponent`, `LegendComponent`, `DataZoomComponent`, `MatrixComponent` | `src/component/{type}/install.ts` |
| Renderers | `CanvasRenderer`, `SVGRenderer` | `src/renderer/installCanvasRenderer.ts`, `installSVGRenderer.ts` |
| Coord systems | `GridSystem` (cartesian), `PolarSystem`, `GeoSystem`, `SingleAxisSystem`, `ParallelSystem`, `CalendarSystem`, `MatrixSystem` | `src/coord/{system}/install.ts` |
| Features | `UniversalTransition`, `LabelLayout`, `AxisBreak`, `LegacyGridContainLabel`, `ScatterJitter` | `src/feature/*` |

### Coordinate systems

| System | Source folder | Used by | Notes |
|---|---|---|---|
| `cartesian` (grid) | `src/coord/cartesian/` | line, bar, scatter, heatmap, candlestick, boxplot, custom | x/y axes; supports breaks (v6) |
| `polar` | `src/coord/polar/` | line, bar, scatter, heatmap | angle + radius axes |
| `geo` | `src/coord/geo/` | map, scatter, heatmap, lines, custom | Requires registered map (`registerMap`) |
| `single` | `src/coord/single/` | scatter, heatmap, themeRiver | One-axis (typically time) |
| `parallel` | `src/coord/parallel/` | parallel, lines | N parallel axes |
| `calendar` | `src/coord/calendar/` | heatmap, scatter, graph, custom | Year-grid heatmap layout |
| `matrix` (v6 NEW) | `src/coord/matrix/` | scatter, line, bar, heatmap, custom | Cell-based matrix layout |
| `radar` | `src/coord/radar/` | radar | Note: separate from coord folder; treated specially |

### Build flavors and entry points

From `package.json` `exports` (dependencies.cbf:111-238):

| Import path | Use case |
|---|---|
| `echarts` | Full bundle. Convenience for development. |
| `echarts/core` | Empty engine; pair with `use([...])` for production tree-shaking. |
| `echarts/charts` | All chart `install` functions as named exports (`BarChart`, `LineChart`, …) |
| `echarts/components` | All component installers |
| `echarts/features` | Optional features (`UniversalTransition`, `LabelLayout`, …) |
| `echarts/renderers` | `CanvasRenderer`, `SVGRenderer` |
| `echarts/index.common` | Pre-bundled common subset |
| `echarts/index.simple` | Pre-bundled minimal (line/bar/pie + tooltip/legend) |
| `echarts/index.blank` | Engine-only (you must `use()` everything) |
| `echarts/ssr/client/index` | `hydrate()` for SSR-rendered SVG |
| `echarts/extension/bmap/bmap` | Baidu Maps coord system |
| `echarts/extension/dataTool/*` | `gexf` parser, `prepareBoxplotData` |
| `echarts/lib/chart/*` | Per-chart installer (also `lib/component/*`, `lib/i18n/*`, `lib/theme/*`) |
| `echarts/dist/echarts.{esm,common,simple}{,.min}.{js,mjs}` | Pre-built dist files |

Type definitions are split (`types/dist/{all,charts,components,core,echarts,features,option,renderers,shared}.d.ts`) so tree-shaken bundles can have correspondingly narrow type imports.

---

## System Requirements

### Browser runtime

| Requirement | Detail |
|---|---|
| **JS runtime** | ES5+ (transpiled output). Modern bundles target ES2015. |
| **DOM APIs** | Required: `<canvas>` + Canvas 2D context **OR** `<svg>` + SVG DOM |
| **Window APIs** | `requestAnimationFrame`, `addEventListener`, `getComputedStyle`, `devicePixelRatio` |
| **Resize observation** | `ResizeObserver` (preferred) or manual `resize()` calls |
| **Touch / pointer** | Optional; enables `useCoarsePointer` mobile mode |
| **Workers** | Not required (no Web Worker usage in core) |

### Build / Node

| Requirement | Detail |
|---|---|
| Node.js | ≥ 14 (used by `build/build.js`) |
| TypeScript | 4.4.3 (devDependency, declarations published) |
| Rollup | 2.34.2 |
| esbuild | 0.8.39 (used by `build/dev-fast.js`) |
| Terser | 5.16.x (minification) |
| ESLint | 7.x (`@typescript-eslint` 4.x) |
| Jest | 26.x (`jest-canvas-mock` 2.5+) |
| Puppeteer | 23.x (visual regression in `test/runTest/`) |

### SSR runtime

| Requirement | Detail |
|---|---|
| Node | Any LTS that runs `zrender` (uses `XMLSerializer` polyfill or none for SVG string mode) |
| `init` opts | `{ ssr: true, renderer: 'svg' }` |
| Output | `chart.renderToSVGString()` |
| Hydration | Browser bundle imports `echarts/ssr/client/index` and calls `hydrate(dom, options)` |

### Data scale guidance

| Data points / series | Recommendation |
|---|---|
| < 1,000 | Default settings, any renderer |
| 1,000 – 50,000 | Canvas renderer; consider `progressive` rendering on the series; enable `large: true` (line/scatter/bar) |
| 50,000 – 500,000 | Canvas; `appendData` streaming; `useDirtyRect: true`; downsample via `dataset.transform` or `series.sampling: 'lttb'` |
| > 500,000 | Always Canvas; use `lines` series with `large` mode + GL-backed extension if available; reduce label rendering; disable animations |

---

## Configuration Reference

ECharts is **option-driven** — there is no `.env`, no config file, no global mutable settings beyond what is set per-instance via `init()` opts and per-render via `setOption()`. Three levels of configuration matter to operators.

### Level 1 — `init(dom, theme?, opts?)` (per-instance)

| Option | Type | Default | Effect |
|---|---|---|---|
| `renderer` | `'canvas' \| 'svg'` | `'canvas'` | Painter selection. Switching at runtime requires `dispose()` + new `init()`. |
| `useDirtyRect` | `boolean` | `false` | Canvas-only. Repaints only changed regions. Reduces CPU on incremental updates. |
| `useCoarsePointer` | `'auto' \| boolean` | `'auto'` | Mobile-friendly enlarged hit areas for touch. |
| `pointerSize` | `number` | unset | Pixel radius for hit-tolerance when `useCoarsePointer` is on. |
| `ssr` | `boolean` | `false` | Server-rendering mode. Combine with `renderer: 'svg'`. Skips DOM event binding. |
| `locale` | `string \| object` | `'EN'` | Locale id (must be registered) or full locale object. |
| `devicePixelRatio` | `number` | `window.devicePixelRatio` | Override canvas DPR; lower for perf, higher for retina. |
| `width` | `number \| 'auto'` | container width | Initial canvas width. |
| `height` | `number \| 'auto'` | container height | Initial canvas height. |

### Level 2 — `setOption(option, opts?)` (per-render)

`option` is the entire chart definition. The full schema is too large to enumerate here (every chart type, component, axis, item-style, label, and emphasis state has its own subtree). Top-level keys:

| Key | Type | Purpose |
|---|---|---|
| `title` | object | Chart title and subtitle |
| `legend` | object | Legend behavior + scroll mode |
| `tooltip` | object | Tooltip trigger + formatter |
| `grid` | object | Cartesian plot area positioning |
| `xAxis` / `yAxis` | object \| array | Cartesian axes (single or multiple) |
| `polar` / `radar` / `geo` / `singleAxis` / `parallel` / `calendar` / `matrix` | object \| array | Other coordinate systems |
| `dataZoom` | array | Zoom controls (`type: 'inside' \| 'slider'`) |
| `visualMap` | array | Color/size mapping legends |
| `toolbox` | object | Built-in feature buttons (saveAsImage, dataView, restore, …) |
| `axisPointer` | object | Crosshair pointer config |
| `dataset` | object \| array | Declarative data + transforms (replaces inline `series.data` for many cases) |
| `series` | array | Required. List of series; each has its own `type`. |
| `animation` | boolean | Enable/disable all animations. |
| `animationDuration` | number \| function | Default 1000 ms. |
| `animationEasing` | string | Default `'cubicOut'`. |
| `animationDelay` | number \| function | Per-element delay (e.g. `(idx) => idx * 10`). |
| `useUTC` | boolean | Default `false`. Forces time-axis interpretation in UTC. |
| `media` | array | Responsive option overrides keyed on viewport size. |
| `aria` | object | Accessibility config (decal generation, aria-label generation). |
| `darkMode` | boolean \| 'auto' | Toggle dark-mode color resolution. |
| `color` | string[] | Series default palette. |
| `backgroundColor` | string | Whole-canvas background. |
| `textStyle` | object | Default font for all text elements. |

`setOption` second-arg `opts`:

| Field | Default | Effect |
|---|---|---|
| `notMerge` | `false` | If `true`, replaces the entire option (otherwise deep-merged into existing). |
| `replaceMerge` | array of component types | Component types to wholly replace rather than merge. |
| `lazyUpdate` | `false` | Defer the actual render until next animation frame (batch multiple `setOption` calls). |
| `silent` | `false` | Suppress events emitted from this update. |
| `transition` | object | Universal-transition overrides. |
| `replaceAnimation` | `false` | Force-replace currently running animations. |

### Level 3 — module-level

| Function | Purpose |
|---|---|
| `echarts.use(installers[])` | Register chart types, components, renderers, features. Required for tree-shaken builds. |
| `echarts.registerTheme(name, theme)` | Add a named theme (referenced by `init(dom, name)`). |
| `echarts.registerMap(name, geoJson, specialAreas?)` | Register a geo map (required before using `series.type: 'map'` or `geo` component with that name). |
| `echarts.getMap(name)` | Retrieve registered map data. |
| `echarts.registerLocale(name, locale)` | Add a locale (i18n strings + date formats). |
| `echarts.connect(group)` | Synchronize tooltips, axisPointers, dataZoom across charts in a `group`. |
| `echarts.disconnect(group)` | Reverse of `connect`. |
| `echarts.dispose(target)` | Dispose by DOM, id, or instance. |
| `echarts.getInstanceByDom(dom)` | Lookup. |
| `echarts.getInstanceById(id)` | Lookup. |

### Negative knowledge — what does NOT exist

To prevent fabrication, the following commonly-assumed configuration does **not** exist in v6.0.0:

- **No environment variables.** ECharts reads no `process.env` at runtime; bundle-time `__DEV__` is the only build flag and is replaced by Rollup.
- **No global config file.** No `echarts.config.js`, no `.echartsrc`. Pure JS API.
- **No CLI binary.** `echarts` is not a command; the package has no `bin` field. The `build/build.js` script is internal-only.
- **No automatic data fetching.** ECharts never issues HTTP requests on its own. Data is always provided by the host.
- **No persistence layer.** No localStorage, no cookies, no IndexedDB writes by ECharts itself.
- **No telemetry / analytics.** No outbound network calls of any kind.
- **No license key / activation.** Apache-2.0; no key required.

> [!IMPORTANT]
> The negative-knowledge list above is exhaustive for v6.0.0. If your team's documentation or wiki references ECharts environment variables, config files, or CLI commands, those references are incorrect — ECharts is configured entirely through its JavaScript API.

---

## Deployment

### Bundling strategies

#### Strategy A — Pre-bundled CDN (zero build)

Best for static sites, demos, and admin dashboards where bundle size is not critical.

```html
<script src="https://cdn.jsdelivr.net/npm/echarts@6.0.0/dist/echarts.min.js"></script>
```

Variants: `echarts.common.min.js` (smaller, common subset), `echarts.simple.min.js` (smallest, line/bar/pie only).

**Operational notes:** pin a specific version (`@6.0.0`, never `@latest`); add Subresource Integrity (`integrity="sha384-..."`); host a self-mirrored copy if your CSP forbids third-party CDNs.

> [!WARNING]
> Never use `@latest` or unpinned CDN URLs in production. A breaking change in a patch release could silently break your dashboards across all deployed instances simultaneously.

#### Strategy B — npm + tree-shaken `use()` (recommended for prod)

```ts
import * as echarts from 'echarts/core';
import { LineChart, BarChart } from 'echarts/charts';
import {
  GridComponent, TooltipComponent, LegendComponent, DataZoomComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import { LabelLayout, UniversalTransition } from 'echarts/features';

echarts.use([
  LineChart, BarChart,
  GridComponent, TooltipComponent, LegendComponent, DataZoomComponent,
  CanvasRenderer,
  LabelLayout, UniversalTransition,
]);
```

Result: production bundle typically 150–300 KB minified+gzipped vs. ~1 MB for the full bundle.

#### Strategy C — SSR

```ts
// Server (Node):
import * as echarts from 'echarts';
const chart = echarts.init(null, null, {
  renderer: 'svg', ssr: true, width: 600, height: 400,
});
chart.setOption(option);
const svg = chart.renderToSVGString();
chart.dispose();
// Send `svg` in HTML payload.

// Client (browser):
import { hydrate } from 'echarts/ssr/client';
hydrate(domElement, { option, /* same as server */ });
```

The hydrate path attaches event handlers to the existing SVG without re-painting.

#### Strategy D — Self-hosted dist

Copy `node_modules/echarts/dist/echarts.min.js` into your `static/` and reference with a relative URL. Useful in airgapped or strict-CSP environments.

### CSP (Content Security Policy)

ECharts itself does **not** evaluate strings as code. It is compatible with strict CSP. Considerations:

| CSP directive | Required for ECharts? |
|---|---|
| `script-src` | Allow self (or your CDN). No `'unsafe-eval'` needed. |
| `style-src` | If you use `'unsafe-inline'` styles in custom-graphic, allow accordingly. ECharts itself does not inject style tags. |
| `img-src` | Required if you use `series.symbol: 'image://...'` or pictorialBar with image symbols. |
| `connect-src` | Not required by ECharts; only if your code fetches data. |
| `worker-src` | Not required. |
| `font-src` | Required if labels reference custom web fonts. |

`getDataURL()` and `getConnectedDataURL()` produce data: URIs purely client-side; no network egress.

### Deployment checklist

- [ ] Pin exact version (`echarts@6.0.0`, no caret/tilde) in production lockfiles.
- [ ] Use the tree-shaken `use()` pattern; verify bundle size with `webpack-bundle-analyzer` or equivalent.
- [ ] Set `useDirtyRect: true` for canvas charts that update incrementally.
- [ ] Decide renderer: Canvas for perf/large data; SVG for accessibility, vector export, or tiny-DOM constraints.
- [ ] Register only the locales your audience needs (each adds ~10–30 KB).
- [ ] Register only the maps you actually render (`world.json` is ~700 KB).
- [ ] Configure `ResizeObserver` or `window.resize` listener → `chart.resize()`.
- [ ] Always call `chart.dispose()` in component unmount paths to free Canvas/SVG GPU resources.
- [ ] Verify SSR and hydration if you ship server-rendered charts.
- [ ] Add accessibility: enable `aria.enabled: true` and provide `aria.label.description`.
- [ ] If embedding user-supplied option, sanitize formatter functions (see Security).
- [ ] Subscribe to `apache/echarts` CVE feeds and the ASF security mailing list.

---

## Operations

ECharts has no daemon, no log file, no metric exporter. "Operations" means **monitoring the host application** for issues caused by the chart instance.

### Lifecycle management

```
init(dom, theme?, opts?)  →  ECharts instance
   ↓
setOption(option)          →  render
   ↓ (repeat as data changes)
resize() | dispatchAction(...) | clear() | appendData(...)
   ↓
dispose()                  →  release Canvas/SVG, detach listeners, free zrender scene
```

**Always dispose.** Failure to call `dispose()` on unmount leaks Canvas-backed buffers and prevents GC of the ECharts instance. In React: call inside `useEffect` cleanup. In Vue: `onBeforeUnmount`. In Angular: `ngOnDestroy`.

> [!CAUTION]
> A single missed `dispose()` call in a SPA can leak 10–50 MB per chart instance (Canvas buffer + zrender scene graph + event listeners). In dashboards that mount/unmount charts on tab switches, this compounds quickly and will eventually crash the browser tab.

### Resize strategy

ECharts does **not** auto-resize. Hook `ResizeObserver`:

```ts
const ro = new ResizeObserver(() => chart.resize());
ro.observe(container);
// On unmount: ro.disconnect(); chart.dispose();
```

For mobile orientation changes, also hook `window.addEventListener('orientationchange', () => chart.resize())`.

### Health signals to monitor

| Signal | How | Indicates |
|---|---|---|
| Frame drops during render | `requestAnimationFrame` timing in dev tools | Too many series / data points; switch to canvas + dirty-rect, downsample. |
| Memory growth | DevTools heap snapshot | Missing `dispose()` calls; check for retained DOM containers. |
| Long task on `setOption` | Performance profiler | Missing `lazyUpdate`; consider splitting updates or `replaceMerge`. |
| Error on `init()` | "Initialize failed: invalid dom." (`src/core/echarts.ts:2797`) | DOM not yet attached, container has zero dimensions, or non-element passed. |
| Error in `renderToCanvas` / `renderToSVGString` | "renderToCanvas can only be used in the canvas renderer." (`src/core/echarts.ts:836`) / "renderToSVGString can only be used in the svg renderer." (`src/core/echarts.ts:852`) | Wrong renderer for the method called. |
| "Option should contains series." | `src/model/Global.ts:926` | `setOption` called with no `series[]`. |
| "render method must been implemented" | `src/view/Chart.ts:153` | Custom chart subclass missing `render()`. |
| "BMap api is not loaded" / "Only one bmap component can exist" | `extension-src/bmap/BMapCoordSys.ts:173,177` | Baidu Map JS not loaded before ECharts uses it; or duplicate bmap config. |

### Operational runbooks

#### Runbook: Chart appears blank
1. Verify container has non-zero width/height (CSS).
2. Check console for `"Initialize failed: invalid dom."`
3. Confirm `setOption` was called and `option.series` is non-empty.
4. For `series.type: 'map'`, confirm `registerMap()` ran first.
5. Inspect with `chart.getOption()` to see what model state exists.

#### Runbook: Memory leak in SPA
1. Open DevTools → Memory → take heap snapshot.
2. Search for `ECharts` constructor instances.
3. If retained, find the DOM container; the framework component likely did not call `dispose()`.
4. Add `dispose()` to unmount lifecycle.

#### Runbook: Slow update with large dataset
1. Confirm `renderer: 'canvas'`.
2. Set `useDirtyRect: true` at `init`.
3. On the affected series, set `large: true` and `progressive: 5000` (line/scatter/bar).
4. For streaming data, prefer `chart.appendData({ seriesIndex, data })` over re-`setOption`.
5. Reduce label/axis tick density; disable animations on update (`setOption(opt, { lazyUpdate: true })` + `animation: false`).

#### Runbook: SSR hydration mismatch
1. Ensure server and client receive the **same** `option` (serialize once).
2. Both sides must `use([...])` the same installers.
3. Same `width`/`height` in `init()` opts on both sides.
4. Date/timezone: set `useUTC: true` to avoid server/client timezone divergence.

### Observability

ECharts emits chart events via `chart.on(eventName, handler)`. Useful events for instrumentation:

| Event | When |
|---|---|
| `rendered` | After a render completes (one-shot per frame) |
| `finished` | Animations complete |
| `click`, `dblclick`, `mousedown`, `mouseup`, `mouseover`, `mouseout` | DOM-style |
| `legendselectchanged` | User toggled a legend item |
| `datazoom` | DataZoom range changed |
| `brushselected` | Brush component selection changed |
| `axisareaselected` | Parallel axis brushed |
| `restore` | Toolbox restore clicked |

Integrate with your observability platform by hooking `rendered` for render-rate metrics and `error`-thrown paths via global `window.addEventListener('error')`.

> [!TIP]
> The `rendered` event's `params.elapsedTime` is the most reliable signal for detecting render regression. Track its P95 over time — a sudden jump after a dependency update or option change indicates a performance problem before users notice.

---

## Performance Tuning

| Knob | Where | Effect |
|---|---|---|
| `renderer: 'canvas'` | `init()` | Best perf for large data and animations. |
| `useDirtyRect: true` | `init()` | Canvas-only; repaint only changed regions. |
| `devicePixelRatio` | `init()` | Lower (e.g. `1`) on retina to halve fill cost; trade for sharpness. |
| `progressive` | `series` | Render N points per frame; smooths large initial render. |
| `large: true`, `largeThreshold` | `series` (line/scatter/bar) | Switch to optimized batch path. |
| `sampling: 'lttb' \| 'average' \| 'max' \| 'min'` | `series.line` | Downsample to viewport pixel count. |
| `animation: false` | top-level option | Skip animations entirely. |
| `lazyUpdate: true` | `setOption` opts | Coalesce multiple updates within one frame. |
| `replaceMerge` | `setOption` opts | Wholly replace components rather than deep-merge (faster + avoids stale fields). |
| `appendData` | instance method | Streaming-append rows without rebuilding `SeriesData`. |
| `series.silent: true` | series | Skip mouse-hit-test geometry maintenance. |
| `series.zlevel` | series | Group into separate canvases; updates to one don't repaint others. |

### When to drop animations

- During rapid streaming (e.g. > 5 updates/sec): set `animation: false` at top level.
- During programmatic `dataZoom` from cursor: animations cause visible lag; disable on dataZoom updates.
- For SSR: animations are irrelevant; set `animation: false`.

---

## Security

### Threat model

ECharts runs **entirely in the host's process** (browser tab or Node). It does not introduce new network endpoints or persistent state. The threat surface is therefore:

1. **Untrusted `option` injection** — if your application accepts user-authored options (e.g. a dashboard editor), an attacker may pass formatter callbacks, image URLs, or HTML strings.
2. **Untrusted data** — series data fields rendered into tooltips/labels.
3. **Untrusted maps** — registered GeoJSON contains arbitrary feature names that surface in tooltips.
4. **Bundle integrity** — supply chain (CDN tampering, npm package compromise).

### Mitigations

| Risk | Mitigation |
|---|---|
| **XSS via tooltip formatter** | Tooltip `formatter` accepts a string template **or** a function. The function may return a string that is set as `innerHTML`. Sanitize: prefer the *string* template form (auto-escapes); if you must use a function, return DOM nodes (object form `{ html, …}` or use `tooltip.renderMode: 'richText'`). Never concatenate untrusted input into HTML strings. |

> [!WARNING]
> If your application allows users to define their own chart options (e.g., a dashboard builder), treat the entire `option` object as untrusted input. Formatter functions, `graphic` component configs, and `image://` symbol URLs are all potential XSS or SSRF vectors. Whitelist allowed option keys rather than blacklisting dangerous ones.
| **XSS via label `formatter`** | Same. Labels are SVG text or canvas text — generally safe, but rich-text labels (`{a|...}`) parse markup. Sanitize. |
| **XSS via `graphic` component** | The `graphic` component allows raw display-object styles including `text`. Treat any user-provided `graphic` config as untrusted. |
| **CSP-incompatible eval** | ECharts core has no `eval` / `new Function`. Compatible with `script-src 'self'`. |
| **Image symbol SSRF** | `series.symbol: 'image://https://attacker/'` triggers an `<img>` request from the user's browser to that URL. This is the same risk as embedding a `<img>` tag — block via `img-src` CSP. |
| **DoS via huge data** | A malicious option could request 100 M points. Validate data length before passing to ECharts. |
| **Prototype pollution** | ECharts deep-merges options; ensure your option-merge layer rejects `__proto__`, `constructor`, `prototype` keys. (ECharts internal merge uses `hasOwnProperty` checks; risk is in *your* pre-processing.) |
| **Supply chain** | Pin exact version. Use Subresource Integrity for CDN. Audit `package-lock.json`. Subscribe to ASF security advisories. |
| **Map data tampering** | If you accept user-uploaded GeoJSON for `registerMap`, validate the schema and bound coordinates. |

### Renderer-specific notes

- **Canvas**: text rendered as glyphs — no HTML parsing, lower XSS surface. Best default for untrusted-data dashboards.
- **SVG**: text rendered into `<text>` elements; rich-text uses `<tspan>`. Tooltips with `renderMode: 'html'` (default) inject into a sibling DOM node — same XSS rules as any HTML output.

### Reporting vulnerabilities

ECharts is governed by the Apache Software Foundation. Security issues should be reported to **[email removed]** (or the ECharts-specific list `[email removed]` if available). Do not file public GitHub issues for vulnerabilities.

### Audit trail

ECharts emits no logs of its own. If you need an audit trail of user interactions:

```ts
chart.on('click', (params) => audit.log('chart-click', { name: params.name, value: params.value }));
chart.on('legendselectchanged', (params) => audit.log('legend-toggle', params));
chart.on('datazoom', (params) => audit.log('zoom', params));
```

---

## Internationalization & Theming

### i18n

53 locales ship in `i18n/`. Built-ins (registered via `src/i18n/`):

```
AR, BG, CA, CS, DA, DE, EL, EN (default), ES, ET, FA, FI, FR, HE, HR,
HU, ID, IT, JA, KO, LT, LV, MS, NL, NO, PL, PT-br, PT, RO, RU, SI, SK,
SL, SR, SV, TH, TR, UK, VI, ZH (Simplified Chinese), …
```

Custom locale:

```ts
import * as echarts from 'echarts/core';
echarts.registerLocale('myLocale', {
  time: { month: ['Jan','Feb',...], dayOfWeek: [...], /* … */ },
  legend: { selector: { all: 'All', inverse: 'Inv' } },
  toolbox: { brush: { title: { rect: 'Rect', polygon: 'Poly', /* … */ } } },
  series: { typeNames: { pie: 'Pie chart', /* … */ } },
  // … see src/i18n/lang*.ts for full key list
});
echarts.init(dom, null, { locale: 'myLocale' });
```

### Theming

37 themes in `theme/` plus `theme/tool/` (theme builder). Built-in themes registered automatically on import; custom themes via:

```ts
echarts.registerTheme('corporate', {
  color: ['#0066cc', '#ff6600', /* palette */],
  backgroundColor: '#ffffff',
  textStyle: { fontFamily: 'Inter, sans-serif' },
  title: { textStyle: { color: '#1a1a1a' } },
  /* … per-component styles … */
});
echarts.init(dom, 'corporate');
```

Theme JSON files in `theme/*.json` can be loaded at runtime and passed directly:

```ts
fetch('/themes/corporate.json').then(r => r.json()).then(theme => {
  echarts.init(dom, theme);
});
```

---

## Testing

### Test layers

| Layer | Tool | Location | Run |
|---|---|---|---|
| Unit tests | Jest 26 + `jest-canvas-mock` | `test/ut/spec/**/*.spec.ts` | `npm test` |
| Type-definition tests | dtslint + `@definitelytyped/utils` | `test/types/` | `npm run test:dts` |
| Visual regression | Puppeteer 23 + pixelmatch | `test/runTest/` | `npm run test:visual` |
| Header check | custom script | `build/checkHeader.js` | `npm run checkheader` |
| Lint | ESLint 7 + `@typescript-eslint` 4 | `.eslintrc` | `npm run lint` |
| Type check | `tsc --noEmit` | tsconfig | `npm run checktype` |

### Visual regression workflow

`test/runTest/server.js` (1909 lines) runs a Puppeteer-driven server. Test pages live under `test/data/`. Snapshots are stored per-version; mismatches produce diff images. The store version (recorded baseline) and run version must match — error: *"Unmatched store version and run version."* (`test/runTest/server.js:366`).

### CLI for visual tests

```
node test/runTest/cli.js --tests <glob> --expected <version>
```

Required args (errors): *"Tests are required"* (`test/runTest/cli.js:64`), *"Expected version is required"* (`test/runTest/cli.js:67`).

### Continuous integration recommendations

- Run `lint` + `checktype` + `test` on every PR.
- Run `test:visual` on a stable Linux runner (font rendering is platform-sensitive; expect baseline drift on macOS/Windows).

> [!NOTE]
> Visual regression baselines are recorded per-version. If the store version and run version mismatch, the test harness errors with "Unmatched store version and run version." Always re-record baselines after upgrading ECharts or Puppeteer.
- Build all flavors (`npm run release`) before a release tag and verify each `dist/*.js` parses with `npm run lint:dist`.

---

## Code Patterns & Conventions

### TypeScript style

- **No semicolons inside object literals**, two-space indent (Apache convention).
- **All public types live in `src/util/types.ts`** and re-exported via `src/echarts.{all,common,simple}.ts`.
- **Interfaces for option types** named `XxxOption`, e.g. `LineSeriesOption`, `GridComponentOption`.
- **Mixin classes** for shared model behavior — see `src/model/mixin/` (palette, area, bordered, time, ...). Applied with TypeScript declaration merging + `mixin()` helper.
- **Branded types** for ID + dimension safety (e.g. `OptionDataItemObject` vs `OptionDataValue`).

### Naming conventions

| Pattern | Example | Meaning |
|---|---|---|
| `XxxModel` | `SeriesModel`, `GridModel` | Option-tree wrapper class |
| `XxxView` | `LineView`, `LegendView` | DOM/zrender renderer |
| `XxxOption` | `BarSeriesOption` | TS interface for a piece of `option` |
| `installXxx` | `installLineChart` | Plugin registrar consumed by `use()` |
| `*Helper.ts` | `referHelper.ts` | Pure helper module (no class) |

### Common patterns

- **`encode`** — series.encode maps dataset dimensions to visual channels; consistent across all series types.
- **`emphasis` / `select` / `blur`** — universal interaction states. Each component supports `emphasis: { itemStyle, label, ... }`.
- **`zlevel` + `z`** — layer ordering: `zlevel` creates a separate canvas; `z` is in-canvas paint order.
- **`silent: true`** — suppress hit-testing on a series or graphic.

### Custom chart authoring

Subclass `ChartView` (`src/view/Chart.ts:98`):

```ts
class MyChartView extends ChartView {
  static type = 'mychart';
  type = MyChartView.type;

  render(seriesModel: MySeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
    // Use this.group as the parent zrender Group.
    // Read coord-system: seriesModel.coordinateSystem
    // Read data: seriesModel.getData()
    // Build display objects, add to this.group
  }
}
```

Failure to override → error: *"render method must been implemented"* (`src/view/Chart.ts:153`).

> [!IMPORTANT]
> Custom chart and component classes must be registered via an `install` function passed to `echarts.use()`. Calling `registerClass` directly still works but bypasses tree-shaking — your custom type will be bundled even by consumers who never use it.

---

## Extending ECharts

### Custom series via `series.type: 'custom'`

The `custom` chart type (`src/chart/custom/`) lets you supply a `renderItem` function that emits zrender display objects per data row. No subclassing required. Use this for bespoke shapes when a built-in chart doesn't fit.

### Custom component

1. Define a `ComponentModel` subclass: option type, defaults, dependencies.
2. Define a `ComponentView` subclass: render display objects.
3. Register: `ComponentModel.registerClass()` + `ComponentView.registerClass()`.
4. Export an `install` function that calls `registerComponentModel` + `registerComponentView`.

### Custom coordinate system

See `extension-src/bmap/` as the canonical example. Implement the `CoordinateSystem` interface (defined in `src/coord/CoordinateSystem.ts`):

```ts
interface CoordinateSystem {
  type: string;
  dimensions: string[];
  dataToPoint(data: number[]): number[];
  pointToData?(point: number[]): number[];
  containPoint(point: number[]): boolean;
  // …
}
```

Register with `CoordinateSystemManager.register(type, creator)` (`src/core/CoordinateSystem.ts:46`).

### Custom data transform

`echarts.registerTransform({ type: 'myorg:filter', transform(params) { … } })`. Used inside `dataset.transform`.

---

## Repository Structure

```
echarts/
├── build/                     Build orchestration (Rollup configs, dev-fast, i18n bundler)
├── dist/                      Pre-built output (ignored in source; produced by `npm run release`)
├── extension/                 Pre-built extensions (ignored)
├── extension-src/             Extension source
│   ├── bmap/                  Baidu Maps coord system (5 files)
│   └── dataTool/              gexf parser, prepareBoxplotData (3 files)
├── i18n/                      53 locale JS files (legacy CommonJS form)
├── lib/                       Per-module entry shims (ignored — generated)
├── licenses/                  Third-party license texts
├── src/                       TypeScript source (1,909 files, ~5.49 M chars)
│   ├── core/                  Engine: echarts.ts, Scheduler, Task, CoordinateSystem
│   ├── model/                 Global, Component, Series, OptionManager, referHelper
│   ├── data/                  SeriesData, DataStore, Source, Graph, Tree, Differ
│   ├── chart/                 23 chart-type folders
│   ├── component/             33 component-type folders
│   ├── coord/                 12 coord-system folders
│   ├── visual/                Visual mappings (color, symbol, decal, …)
│   ├── processor/             Data-stage operators (filter, sample, stack)
│   ├── layout/                Cross-series layout helpers
│   ├── scale/                 Interval, Log, Ordinal, Time, AxisBreak
│   ├── label/                 LabelManager + helpers
│   ├── animation/             UniversalTransition, AnimationWrap, custom transitions
│   ├── view/                  Chart.ts, Component.ts base view classes
│   ├── renderer/              installCanvasRenderer, installSVGRenderer
│   ├── theme/                 Default + dark theme registration
│   ├── i18n/                  Locale registration helpers
│   ├── loading/               Default loading spinner
│   ├── preprocessor/          Legacy option migrations
│   ├── legacy/                Deprecated-shape compatibility shims
│   ├── export/                Public API surface and per-flavor entry points
│   ├── util/                  Cross-cutting utilities (KDTree, throttle, conditional expressions, …)
│   ├── echarts.all.ts         Full bundle entry
│   ├── echarts.common.ts      Common-subset bundle entry
│   └── echarts.simple.ts      Minimal bundle entry
├── ssr/
│   └── client/src/            hydrate(dom, options) for SSR
├── test/                      ~600 files: ut/, types/, runTest/, data/, asset/, lib/, node/
├── theme/                     37 theme JSON files + theme/tool/
├── types/                     Declaration generation outputs (ignored)
├── package.json               Multi-entry exports (lines 111-238 of dependencies.cbf)
├── rollup.config.js           Rollup config
├── tsconfig.json              TS 4.4.3 config
└── LICENSE / NOTICE           Apache-2.0 + Apache attribution
```

---

## Build System

### Build commands

| Command | Effect |
|---|---|
| `npm run build` | All flavors UMD + minified (`--type all,common,simple --min`) |
| `npm run build:esm` | ESM bundle (`dist/echarts.esm.mjs`) |
| `npm run build:i18n` | Compile `i18n/*.js` from `src/i18n/lang*.ts` |
| `npm run build:lib` | Build `lib/` per-module shims (consumed by `prepare`) |
| `npm run build:extension` | Build `extension-src/` → `extension/` |
| `npm run build:ssr` | Build `ssr/client/dist/` |
| `npm run dev` | Concurrent watcher + http-server on `test/` |
| `npm run dev:fast` | esbuild-based fast dev build (no minification, no type-check) |
| `npm run release` | Full release: lib + i18n + UMD + ESM + extension + ssr |
| `npm run help` | `node build/build.js --help` |

### Build CLI flags (`build/build.js`)

Discovered from extracted CLI commands (16 total). Common flags:

| Flag | Effect |
|---|---|
| `--type all,common,simple,blank,extension,ssr` | Select flavor(s) to build |
| `--min` | Produce `*.min.js` Terser-minified output alongside non-min |
| `--format umd \| esm \| cjs` | Module format (default UMD for `dist/`) |
| `--prepublish` | Build `lib/` shims used by `package.json` exports |
| `--watch` | Rebuild on source changes |
| `--clean` | Wipe `dist/` before build |

### Output anatomy

```
dist/
├── echarts.js              UMD bundle, all charts/components
├── echarts.min.js          Terser-minified UMD
├── echarts.esm.mjs         ESM bundle
├── echarts.esm.min.mjs     Terser-minified ESM
├── echarts.common.js       UMD common subset
├── echarts.common.min.js   Minified common
├── echarts.simple.js       UMD minimal
├── echarts.simple.min.js   Minified simple
└── extension/
    ├── bmap.js / bmap.min.js
    └── dataTool.js / dataTool.min.js
```

### Type generation

Driven by `@microsoft/api-extractor` 7.31.2 + `@lang/rollup-plugin-dts`. Outputs:

```
types/dist/
├── all.d.ts
├── charts.d.ts
├── components.d.ts
├── core.d.ts
├── echarts.d.ts        (canonical)
├── echarts.d.cts       (CommonJS variant referenced by package.json:23)
├── features.d.ts
├── option.d.ts
├── renderers.d.ts
└── shared.d.ts
```

### Build internals

`build/build.js` orchestrates Rollup with these plugins:

- `@rollup/plugin-node-resolve` 11
- `@rollup/plugin-commonjs` 17
- `@rollup/plugin-replace` 2 (substitutes `__DEV__` → `false` for prod)
- `rollup-plugin-terser` 7 (when `--min`)
- Custom esbuild loader for fast dev mode (`build/dev-fast.js`)

The `dev:fast` path uses esbuild directly for sub-second incremental rebuilds; production uses Rollup for tree-shaking quality.

---

## Error Reference

The library raises 31 distinct errors (extracted from `_briefing/extracted/error_messages.tsv`). The most operationally significant:

| Error | File:line | Cause / Fix |
|---|---|---|
| `Option should contains series.` | `src/model/Global.ts:926` | `setOption` called with empty/missing `series[]`. |
| `xAxis ` / `yAxis ` (component not found) | `src/model/referHelper.ts:113,120` | Series references an axis index that wasn't declared. |
| `singleAxis should be specified.` | `src/model/referHelper.ts:149` | Series uses single coord but no `singleAxis` component. |
| `angleAxis option not found` | `src/model/referHelper.ts:169` | Polar series with no `polar.angleAxis`. |
| `radiusAxis option not found` | `src/model/referHelper.ts:172` | Polar series with no `polar.radiusAxis`. |
| `matrix coordinate system should be specified.` | `src/model/referHelper.ts:222` | Series declares `coordinateSystem: 'matrix'` but no `matrix` component (v6 only). |
| `render method must been implemented` | `src/view/Chart.ts:153` | Custom chart subclass missing `render()`. |
| `BMap api is not loaded` | `extension-src/bmap/BMapCoordSys.ts:173` | Baidu Maps SDK script not loaded before chart init. |
| `Only one bmap component can exist` | `extension-src/bmap/BMapCoordSys.ts:177` | Two `bmap` components configured; merge into one. |
| `renderToCanvas can only be used in the canvas renderer.` | `src/core/echarts.ts:836` | Called `renderToCanvas` on an SVG-renderer instance. |
| `renderToSVGString can only be used in the svg renderer.` | `src/core/echarts.ts:852` | Called `renderToSVGString` on a Canvas-renderer instance. |
| `Initialize failed: invalid dom.` | `src/core/echarts.ts:2797` | `init()` passed null/undefined/non-element, or container detached from document. |
| `Illegal priority` | `src/core/echarts.ts:3116` | Custom processor registration with invalid priority enum. |
| `Unknown dimension ` | `src/data/SeriesData.ts:455` | `getDimensionInfo()` called with name not present in `SeriesData`. |
| `Do not supported yet` | `src/data/SeriesData.ts:871` | Dataset transform path that hit unsupported branch. |
| `key must not be ` | `src/animation/customGraphicTransition.ts:424` | Reserved key used in custom-graphic transition definition. |

Test-suite errors (`test/runTest/`, `test/lib/`) appear during local development only and are not user-facing.

---

## Improvements & Tech-Debt Notes

Observations from the v6.0.0 source (open as suggestions; not bugs):

1. **Extracted-fact yield is low for TS-only libraries.** The pipeline counted 0 functions in 1,909 files because all top-level surface is class-method based. Documentation tooling consumers should rely on `index.d.ts` walks, not text extraction, when targeting ECharts.
2. **`src/core/echarts.ts` is 5,000+ lines.** A future refactor could split `ECharts` instance methods (export, hydration, action dispatch) into adjacent files; this would simplify static analysis and tree-shaking.
3. **`src/legacy/` shim layer** exists for deprecated shapes from v3/v4. A v7 release could drop these (with a migration guide), shrinking the engine bundle.
4. **Type-test (`test:dts`) requires a separate npm install** in `test/types/` (declared in `test/types/package.json`). CI should cache that subtree to keep the verification fast.
5. **No first-party React/Vue wrappers in the repo.** Community wrappers exist (`echarts-for-react`, `vue-echarts`); consumers should pin those to ECharts 6 explicitly.
6. **Visual regression baselines are platform-sensitive.** Linux container is the canonical reference; macOS/Windows differ slightly in font rasterization. Document this on the test harness page.
7. **Bundle entries have implicit transitive imports.** `index.common.js` and `index.simple.js` lock in a curated set; consumers wanting different subsets must use the `core` + `use([...])` path, not edit the published flavors.

---

## Contributing

ECharts is governed by the Apache Software Foundation; contributions follow ASF process.

1. **Sign the Apache ICLA** (Individual Contributor License Agreement) before any non-trivial PR.
2. **Discuss large changes** on `[email removed]` before opening a PR.
3. **Branching**: `master` for current major; release branches as `release/X.Y`.
4. **Commit format**: imperative subject, body explains why; reference GitHub issues with `#NNNN`.
5. **Required checks** before PR: `npm run lint`, `npm run checktype`, `npm run test`, `npm run test:dts`, header check.
6. **Visual regression**: add or update snapshots in `test/runTest/` for any visual change; reviewer runs the full suite.
7. **Code style**: enforced by ESLint + `@typescript-eslint`; run `npm run lint:fix`.
8. **Add an `install` function** for any new chart/component/feature so users can tree-shake.
9. **Write at least one Jest unit test** for new logic in `src/`.
10. **Update locale strings** in `src/i18n/lang*.ts` for any new user-visible text.

### Issue triage

Issues are tracked at `https://github.com/apache/echarts/issues`. Selected open threads relevant to operators:

- Memory growth in long-running dashboards (recurring; usually fixed by ensuring `dispose()` on unmount).
- DataZoom + scroll-wheel interaction inside scrollable containers (configure `dataZoom.preventDefaultMouseMove`).
- SSR + universal transition mismatch on hydration (workaround: disable universal transition during SSR).

---

## Quick Reference Card

### Module-level API

```ts
import * as echarts from 'echarts/core';

echarts.use(installers);
echarts.init(dom, theme?, opts?);                      // → ECharts instance
echarts.connect(groupIdOrCharts);
echarts.disconnect(groupId);
echarts.dispose(domOrIdOrInstance);
echarts.getInstanceByDom(dom);
echarts.getInstanceById(id);
echarts.registerTheme(name, theme);
echarts.registerMap(name, geoJson, specialAreas?);
echarts.getMap(name);
echarts.registerLocale(name, locale);
```

### Instance API (53 public methods/props selected)

```ts
chart.setOption(option, opts?);
chart.getOption();
chart.getWidth();
chart.getHeight();
chart.getDom();
chart.getZr();                                         // zrender instance (advanced)
chart.resize(opts?);
chart.dispatchAction(action);
chart.on(eventName, query?, handler, context?);
chart.off(eventName, handler?);
chart.showLoading(type?, opts?);
chart.hideLoading();
chart.convertToPixel(finder, value);
chart.convertFromPixel(finder, value);
chart.containPixel(finder, value);
chart.getDataURL(opts?);                               // base64 data URL
chart.getConnectedDataURL(opts?);                      // composite of all connected
chart.appendData({ seriesIndex, data });
chart.clear();
chart.isDisposed();
chart.dispose();
chart.renderToCanvas(opts?);                           // canvas renderer only
chart.renderToSVGString(opts?);                        // svg renderer only
chart.makeActionFromEvent(event);
chart.group;                                           // string; for connect()
```

### Renderer matrix

| Capability | Canvas | SVG |
|---|---|---|
| Default | ✓ | — |
| `useDirtyRect` | ✓ | — |
| `renderToCanvas` | ✓ | ✗ (errors) |
| `renderToSVGString` | ✗ (errors) | ✓ |
| SSR | partial | ✓ (recommended) |
| Best for large data | ✓ | — |
| Best for accessibility | — | ✓ |
| Best for vector export | — | ✓ |

### Config file locations

ECharts has **no config files**. All settings via:
- `init(dom, theme, opts)` → instance settings
- `chart.setOption(option)` → render settings
- `echarts.register*()` → module-level registration

### Required global state

None. ECharts maintains a per-bundle module-level registry for plugins (populated by `use()`), maps (`registerMap`), themes (`registerTheme`), and locales (`registerLocale`). All other state is per-instance.

---

_Generated May 2026 from apache/echarts at c8adaf4. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
