模块化按需引入
减小打包体积,只引入需要的模块 - 从 800KB 到 100KB 的优化之路
📖 概述
ECharts 提供了完整的按需引入机制,可以将打包体积从 800KB+ 减小到 100KB-300KB,对于移动端和性能敏感的应用至关重要。
核心优势:
- ✅ 减小 60-80% 打包体积
- ✅ 加快首屏加载速度
- ✅ 降低内存占用
- ✅ 提升运行时性能
- ✅ Tree Shaking 友好
🔍 核心概念
1. 引入方式对比
全量引入(不推荐)
javascript
// ❌ 打包体积: ~800KB (gzip: ~250KB)
import * as echarts from 'echarts';
const chart = echarts.init(dom);
chart.setOption({
series: [{ type: 'bar', data: [1, 2, 3] }]
});1
2
3
4
5
6
7
2
3
4
5
6
7
问题:
- 引入了所有图表类型(即使只用了一个)
- 引入了所有组件(即使只用了少数几个)
- 打包体积过大
- 首屏加载慢
按需引入(强烈推荐)
javascript
// ✅ 打包体积: ~150KB (gzip: ~50KB)
import * as echarts from 'echarts/core';
import { BarChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import {
TitleComponent,
TooltipComponent,
GridComponent
} from 'echarts/components';
// 注册必须的组件
echarts.use([
BarChart,
TitleComponent,
TooltipComponent,
GridComponent,
CanvasRenderer
]);
const chart = echarts.init(dom);
chart.setOption({
series: [{ type: 'bar', data: [1, 2, 3] }]
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
优势:
- 只引入需要的模块
- 打包体积减小 80%
- 首屏加载快
- 支持 Tree Shaking
2. 模块分类
ECharts 的模块分为以下几类:
3. 模块清单
核心模块
javascript
import * as echarts from 'echarts/core';1
包含:
- ECharts 核心逻辑
- 初始化 API
- setOption API
- 事件系统
体积: ~50KB
图表类型模块
javascript
import {
// 基础图表
BarChart, // 柱状图
LineChart, // 折线图
PieChart, // 饼图
ScatterChart, // 散点图
// 高级图表
RadarChart, // 雷达图
MapChart, // 地图
CandlestickChart, // K线图
HeatmapChart, // 热力图
TreeChart, // 树图
SankeyChart, // 桑基图
GraphChart, // 关系图
GaugeChart, // 仪表盘
FunnelChart, // 漏斗图
PictorialBarChart, // 象形柱图
CustomChart // 自定义系列
} from 'echarts/charts';1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
单个体积: 每个图表 10-30KB
全部引入: ~400KB
组件模块
javascript
import {
// 基础组件
TitleComponent, // 标题
TooltipComponent, // 提示框
GridComponent, // 网格
LegendComponent, // 图例
PolarComponent, // 极坐标
GeoComponent, // 地理坐标系
// 交互组件
DataZoomComponent, // 数据缩放
VisualMapComponent, // 视觉映射
ToolboxComponent, // 工具栏
BrushComponent, // 选框
TimelineComponent, // 时间轴
// 辅助组件
AriaComponent, // 无障碍
MarkLineComponent, // 标记线
MarkPointComponent, // 标记点
MarkAreaComponent // 标记区域
} from 'echarts/components';1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
单个体积: 每个组件 5-20KB
全部引入: ~200KB
渲染器模块
javascript
import {
CanvasRenderer, // Canvas 渲染器(默认)
SVGRenderer // SVG 渲染器
} from 'echarts/renderers';1
2
3
4
2
3
4
体积:
- CanvasRenderer: ~30KB
- SVGRenderer: ~25KB
💡 使用场景
场景 1: 简单柱状图项目
需求: 只需要柱状图和基础配置
javascript
// src/utils/echarts.js
import * as echarts from 'echarts/core';
import { BarChart } from 'echarts/charts';
import {
TitleComponent,
TooltipComponent,
GridComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([
BarChart,
TitleComponent,
TooltipComponent,
GridComponent,
CanvasRenderer
]);
export default echarts;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
打包体积: ~100KB (gzip: ~35KB)
体积减少: 87.5%
场景 2: BI 数据看板
需求: 多种图表 + 完整交互
javascript
// src/utils/echarts.js
import * as echarts from 'echarts/core';
import {
BarChart,
LineChart,
PieChart,
RadarChart
} from 'echarts/charts';
import {
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
DataZoomComponent,
VisualMapComponent,
ToolboxComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([
BarChart,
LineChart,
PieChart,
RadarChart,
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
DataZoomComponent,
VisualMapComponent,
ToolboxComponent,
CanvasRenderer
]);
export default echarts;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
打包体积: ~250KB (gzip: ~85KB)
体积减少: 68.7%
场景 3: 移动端 H5 应用
需求: 极致优化,最小体积
javascript
// src/utils/echarts.js
import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import {
TooltipComponent,
GridComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([
LineChart,
TooltipComponent,
GridComponent,
CanvasRenderer
]);
// 全局优化配置
echarts.registerTheme('mobile', {
color: ['#5470c6', '#91cc75'],
fontSize: 12
});
export default echarts;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
打包体积: ~80KB (gzip: ~28KB)
体积减少: 90%
🔧 配置详解
1. Vue 3 项目配置
Vite 配置
javascript
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
// 优化配置
build: {
rollupOptions: {
output: {
manualChunks: {
echarts: ['echarts/core', 'echarts/charts', 'echarts/components']
}
}
}
}
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Vue 组件中使用
vue
<template>
<div ref="chartRef" style="width: 100%; height: 400px"></div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import echarts from '@/utils/echarts'; // 上面创建的入口文件
const chartRef = ref(null);
onMounted(() => {
const chart = echarts.init(chartRef.value);
chart.setOption({
xAxis: { type: 'category', data: ['A', 'B', 'C'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [10, 20, 30] }]
});
});
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2. React 项目配置
Webpack 配置
javascript
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
echarts: {
test: /[\\/]node_modules[\\/]echarts/,
name: 'echarts',
chunks: 'all'
}
}
}
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
React 组件中使用
jsx
import { useEffect, useRef } from 'react';
import echarts from '@/utils/echarts';
function ChartComponent() {
const chartRef = useRef(null);
useEffect(() => {
const chart = echarts.init(chartRef.current);
chart.setOption({
series: [{ type: 'bar', data: [10, 20, 30] }]
});
return () => chart.dispose();
}, []);
return <div ref={chartRef} style={{ width: '100%', height: 400 }} />;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
3. TypeScript 支持
bash
npm install @types/echarts -D1
typescript
// src/types/echarts.d.ts
import type {
EChartsOption,
EChartsType,
ECElementEvent
} from 'echarts';
declare module '@/utils/echarts' {
export function init(dom: HTMLElement): EChartsType;
export function use(components: any[]): void;
}
// 使用
import type { EChartsOption } from 'echarts';
const option: EChartsOption = {
// 现在有完整的类型提示
xAxis: { type: 'category' },
series: [{ type: 'bar', data: [1, 2, 3] }]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
4. CDN 按需引入
html
<!-- 不推荐: 全量引入 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<!-- 推荐: ES Module CDN -->
<script type="module">
import * as echarts from 'https://cdn.jsdelivr.net/npm/echarts@5/+esm';
import { BarChart } from 'https://cdn.jsdelivr.net/npm/echarts@5/charts/+esm';
import { CanvasRenderer } from 'https://cdn.jsdelivr.net/npm/echarts@5/renderers/+esm';
echarts.use([BarChart, CanvasRenderer]);
const chart = echarts.init(document.getElementById('chart'));
chart.setOption({
series: [{ type: 'bar', data: [1, 2, 3] }]
});
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
📝 代码示例
示例 1: 完整的按需引入配置文件
javascript
// src/plugins/echarts.js
import * as echarts from 'echarts/core';
// 根据项目需求选择需要的图表
import {
BarChart,
LineChart,
PieChart,
ScatterChart,
RadarChart,
MapChart,
CandlestickChart,
HeatmapChart,
TreeChart,
SankeyChart,
GraphChart,
GaugeChart,
FunnelChart
} from 'echarts/charts';
// 根据项目需求选择需要的组件
import {
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
PolarComponent,
GeoComponent,
SingleAxisComponent,
ParallelComponent,
CalendarComponent,
GraphicComponent,
ToolboxComponent,
DataZoomComponent,
VisualMapComponent,
TimelineComponent,
AriaComponent,
MarkLineComponent,
MarkPointComponent,
MarkAreaComponent
} from 'echarts/components';
// 根据需要选择渲染器
import {
CanvasRenderer,
SVGRenderer
} from 'echarts/renderers';
// 注册所有需要的模块
echarts.use([
// 图表
BarChart,
LineChart,
PieChart,
ScatterChart,
RadarChart,
MapChart,
CandlestickChart,
HeatmapChart,
TreeChart,
SankeyChart,
GraphChart,
GaugeChart,
FunnelChart,
// 组件
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
PolarComponent,
GeoComponent,
SingleAxisComponent,
ParallelComponent,
CalendarComponent,
GraphicComponent,
ToolboxComponent,
DataZoomComponent,
VisualMapComponent,
TimelineComponent,
AriaComponent,
MarkLineComponent,
MarkPointComponent,
MarkAreaComponent,
// 渲染器
CanvasRenderer,
SVGRenderer
]);
// 全局配置
echarts.registerTheme('custom', {
color: ['#5470c6', '#91cc75', '#fac858', '#ee6666'],
backgroundColor: 'rgba(0,0,0,0)',
textStyle: {
fontFamily: 'Arial, sans-serif',
fontSize: 12
}
});
export default echarts;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
示例 2: 动态按需加载
javascript
// 根据路由动态加载图表模块
class DynamicECharts {
constructor() {
this.initialized = false;
this.echarts = null;
}
async init(requiredModules) {
if (this.initialized) return this.echarts;
// 动态导入核心
const echarts = await import('echarts/core');
// 动态导入需要的模块
const modules = [];
if (requiredModules.includes('bar')) {
const { BarChart } = await import('echarts/charts');
modules.push(BarChart);
}
if (requiredModules.includes('line')) {
const { LineChart } = await import('echarts/charts');
modules.push(LineChart);
}
if (requiredModules.includes('tooltip')) {
const { TooltipComponent } = await import('echarts/components');
modules.push(TooltipComponent);
}
const { CanvasRenderer } = await import('echarts/renderers');
modules.push(CanvasRenderer);
// 注册模块
echarts.use(modules);
this.echarts = echarts;
this.initialized = true;
return echarts;
}
}
// 使用
const loader = new DynamicECharts();
// 在路由守卫中
router.beforeEach(async (to, from, next) => {
if (to.meta.charts) {
await loader.init(to.meta.charts);
}
next();
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
示例 3: 微前端架构中的按需引入
javascript
// 主应用
// main-app/src/echarts-loader.js
export class EChartsLoader {
static async load(subApp) {
const requirements = {
'dashboard': ['bar', 'line', 'pie'],
'monitor': ['line', 'gauge'],
'analysis': ['scatter', 'heatmap', 'tree']
};
const modules = requirements[subApp] || ['bar', 'line'];
const echarts = await import('echarts/core');
const charts = await Promise.all(
modules.map(type => import(`echarts/charts`).then(m => m[`${type.charAt(0).toUpperCase()}${type.slice(1)}Chart`]))
);
const { CanvasRenderer } = await import('echarts/renderers');
echarts.use([...charts, CanvasRenderer]);
return echarts;
}
}
// 子应用
// sub-app-dashboard/main.js
import { EChartsLoader } from 'main-app/echarts-loader';
const echarts = await EChartsLoader.load('dashboard');
const chart = echarts.init(document.getElementById('chart'));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
⚠️ 常见问题
Q1: 如何查看打包体积?
Webpack Bundle Analyzer
bash
npm install webpack-bundle-analyzer --save-dev1
javascript
// webpack.config.js
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'server',
openAnalyzer: true
})
]
};1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
运行:
bash
npm run build -- --analyze1
Vite Bundle Analyzer
bash
npm install rollup-plugin-visualizer --save-dev1
javascript
// vite.config.js
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
visualizer({
open: true,
gzipSize: true,
brotliSize: true
})
]
});1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Q2: Tree Shaking 不生效?
原因: 使用了 CommonJS 或配置错误
解决方案:
javascript
// ✅ 正确: 使用 ES Module
import { BarChart } from 'echarts/charts';
// ❌ 错误: CommonJS
const { BarChart } = require('echarts/charts');
// 检查 package.json
{
"type": "module", // 确保启用 ESM
"sideEffects": false // 标记无副作用
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Q3: 类型定义缺失?
bash
# 安装类型定义
npm install @types/echarts -D
# 或使用官方类型
npm install echarts # v5+ 自带类型1
2
3
4
5
2
3
4
5
typescript
import type { EChartsOption } from 'echarts';
const option: EChartsOption = {
// 完整的类型提示
};1
2
3
4
5
2
3
4
5
Q4: 如何处理版本升级?
javascript
// 版本检测
console.log(echarts.version); // '5.4.3'
// 兼容性处理
if (parseInt(echarts.version) >= 5) {
// ECharts 5+ 语法
echarts.use([BarChart]);
} else {
// ECharts 4 语法
// ...
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
🎯 最佳实践
1. 创建统一的入口文件
javascript
// src/plugins/echarts.js
import * as echarts from 'echarts/core';
// ... 引入需要的模块
echarts.use([...]);
export default echarts;
// 使用时
import echarts from '@/plugins/echarts';1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
优势:
- 统一管理依赖
- 便于维护和更新
- 避免重复引入
2. 定期审查未使用的模块
bash
# 使用 depcheck 检查未使用的依赖
npm install depcheck -D
npx depcheck1
2
3
2
3
移除未使用的模块:
javascript
// 删除不再使用的导入
// import { UnusedChart } from 'echarts/charts'; // 已删除1
2
2
3. 按路由拆分代码
javascript
// router/index.js
const routes = [
{
path: '/dashboard',
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue'),
meta: {
charts: ['bar', 'line', 'pie'] // 声明需要的图表
}
}
];1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
4. 生产环境优化
javascript
// vite.config.js
export default defineConfig({
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true
}
},
rollupOptions: {
output: {
manualChunks: {
'echarts-core': ['echarts/core'],
'echarts-charts': ['echarts/charts'],
'echarts-components': ['echarts/components']
}
}
}
}
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
📊 性能对比
| 引入方式 | 打包体积 | gzip 后 | 首屏加载 | 推荐场景 |
|---|---|---|---|---|
| 全量引入 | 800KB | 250KB | 慢 | 不推荐 |
| 按需引入(简单) | 100KB | 35KB | 快 | 简单项目 |
| 按需引入(中等) | 250KB | 85KB | 中 | BI 看板 |
| 按需引入(复杂) | 400KB | 130KB | 中 | 企业级应用 |
| 动态加载 | 80-400KB | 28-130KB | 最快 | 大型应用 |
体积减少: 60-90%
加载速度提升: 2-5倍
🔗 相关链接
- React/Vue 集成
- TypeScript 支持
- SSR 服务端渲染
- 官方按需引入文档
- Webpack Tree Shaking
最后更新: 2026-04-23
难度等级: ⭐⭐
预计阅读时间: 18 分钟
示例演示
{
"series": [
{
"type": "bar",
"data": [
1,
2,
3
]
}
]
}示例演示
{
"series": [
{
"type": "bar",
"data": [
1,
2,
3
]
}
]
}