二、导出失败:导出模块与导出服务器的排雷
2.1 痛点场景
- 右上角"⋯"菜单点了没反应,或菜单里只有"打印"没有下载项。
- 点"下载 PNG/JPG"后图片空白、控制台报
SecurityError/CORS/Failed to execute 'toDataURL'。 - 用 React / 打包工具后,本地能跑,一导出就报错
exporting is not defined。
2.2 原理解析
导出功能不在 Highcharts Core 里,而是两个独立模块:highcharts/modules/exporting(生成菜单与图片)和 highcharts/modules/export-data(导出 CSV/XLS)。没显式 import 并初始化它们,菜单就不会出现。
默认导出走官方导出服务器 export.highcharts.com;当图表里用了跨域位图(如 plotBackgroundImage、图片型 dataLabels、图片填充)且图片服务器没有返回 CORS 头时,canvas 被"污染",浏览器禁止 toDataURL,于是报 SecurityError。
2.3 官方解法与代码
按当前 @highcharts/react v5 的方式调整。最重要的区别是:在 React 中不要再手动调用旧式模块初始化函数,优先使用 @highcharts/react/modules/* 组件。
1. 原生 JavaScript:加载导出模块
在原生 JavaScript 或传统打包方式中,需要加载并初始化 exporting。如果还要导出 CSV/XLS,则同时加载 export-data:
import Highcharts from 'highcharts';
import Exporting from 'highcharts/modules/exporting';
import ExportData from 'highcharts/modules/export-data';
Exporting(Highcharts);
ExportData(Highcharts);
Highcharts.chart('container', {
title: {
text: '导出示例'
},
exporting: {
enabled: true
},
series: [{
name: '示例数据',
data: [29, 71, 106, 129]
}]
});
不同构建环境对模块导出的形式可能不同。如果使用的是当前 Highcharts ESM 构建,优先遵循对应版本的模块加载方式;不要在同一个项目中混用多个 Highcharts 实例,否则模块可能注册到了错误的实例上。
2. @highcharts/react v5:使用模块组件
当前推荐使用 @highcharts/react@5 的模块组件:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Chart, Title } from '@highcharts/react';
import { Accessibility } from '@highcharts/react/modules/Accessibility';
import { Exporting } from '@highcharts/react/modules/Exporting';
import { Data } from '@highcharts/react/modules/Data';
import { LineSeries } from '@highcharts/react/series/Line';
function App() {
return (
<Chart
options={{
exporting: {
enabled: true,
filename: 'my-chart',
buttons: {
contextButton: {
menuItems: [
'downloadPNG',
'downloadJPEG',
'downloadPDF',
'downloadSVG',
'separator',
'downloadCSV',
'downloadXLS'
]
}
}
}
}}
>
<Title>导出示例</Title>
<Accessibility />
<Exporting />
<Data />
<LineSeries
name="示例数据"
data={[29, 71, 106, 129]}
/>
</Chart>
);
}
createRoot(document.getElementById('container')!).render(<App />);
说明:
Exporting提供导出菜单、打印、PNG/JPEG/PDF/SVG 等功能。Data提供 CSV/XLS 等数据导出功能。Accessibility建议一并启用。- 当前 v5 的模块路径是
@highcharts/react/modules/Exporting,不是旧的@highcharts/react/options/Exporting。 @highcharts/react示例建议使用 Highcharts 12.x 兼容版本。
如果只需要图片导出,不需要 CSV/XLS,可以省略 Data。
3. 菜单不显示或点击无反应
按以下顺序排查:
- 是否加载了
Exporting模块。 - 是否配置了
exporting.enabled: true。 - 是否被全局配置或响应式规则覆盖为
false。 - 是否误用了
exporting.buttons.contextButton.menuItems,并把所需菜单项删掉了。 - 是否项目中存在多个 Highcharts 实例,导致模块加载到另一实例。
- 如果是 React/Next.js,是否在客户端组件中渲染图表。
例如,下面的配置会只保留指定菜单项:
exporting: {
enabled: true,
buttons: {
contextButton: {
menuItems: [
'downloadPNG',
'downloadSVG',
'downloadCSV'
]
}
}
}
如果需要完整默认菜单,也可以不覆盖 menuItems,只设置:
exporting: {
enabled: true
}
4. 导出空白、SecurityError 或 CORS 错误
这通常不是导出菜单问题,而是图表包含跨域图片资源,例如:
chart.plotBackgroundImage- 图片填充
- 图片型数据标签
- 自定义 SVG 中引用的外部图片
- 图片纹理或点图形
浏览器端生成图片时,如果 canvas 使用了没有正确 CORS 响应头的图片,就可能被污染,随后 toDataURL() 会抛出 SecurityError。
处理顺序建议如下:
方案 A:为图片资源配置 CORS
图片服务器应返回类似:
Access-Control-Allow-Origin: https://your-site.example
或在确实允许所有来源时返回:
Access-Control-Allow-Origin: *
同时图片请求必须以匿名 CORS 方式加载。仅在 Highcharts 配置中添加一个 CORS 字段,不能替代图片服务器的响应头。
方案 B:避免导出链路中的位图
如果图表允许,改用:
- 纯色填充
- SVG 图形
- 不依赖外部图片的自定义标记
这是最稳定的客户端导出方案。
方案 C:使用服务端导出
默认导出通常可使用 Highcharts 导出服务器。也可以显式设置:
exporting: {
serverURL: 'https://export.highcharts.com'
}
但需要注意:
- 图表 SVG 中的外部资源必须能被导出服务器访问。
- 内网地址、需要登录的地址、受防火墙保护的资源,导出服务器通常无法访问。
- 将图表或数据发送到第三方服务器可能涉及隐私和合规问题。对敏感数据,建议使用自有导出服务或客户端导出。
5. 内网或离线环境:客户端导出
如果不希望请求 Highcharts 导出服务器,可以使用 offline-exporting:
import Highcharts from 'highcharts';
import Exporting from 'highcharts/modules/exporting';
import OfflineExporting from 'highcharts/modules/offline-exporting';
Exporting(Highcharts);
OfflineExporting(Highcharts);
Highcharts.chart('container', {
exporting: {
enabled: true,
fallbackToExportServer: false,
libURL: '/highcharts/lib/'
},
series: [{
data: [1, 3, 2, 4]
}]
});
libURL 应指向本地依赖文件所在目录,而不是在真正离线环境中继续使用公网 URL。具体依赖和目录内容应根据所使用的 Highcharts 版本和构建方式部署。
对于 React v5,如果项目版本提供对应的 OfflineExporting 模块组件,优先使用:
import { OfflineExporting } from '@highcharts/react/modules/OfflineExporting';
如果当前包版本没有该组件,则通过 Highcharts 的 ESM 模块路径加载:
import 'highcharts/es-modules/masters/modules/offline-exporting.src.js';
不要把旧版 highcharts/modules/* 初始化写法和 React v5 的模块组件方式混在同一个实例上。
6. Next.js 注意事项
Next.js App Router 中,包含图表和导出模块的组件应为客户端组件:
'use client';
此外,Highcharts 依赖浏览器 DOM,不能在服务端渲染阶段创建图表。若仍出现 window is not defined、document is not defined 或模块初始化错误,应检查:
- 图表组件是否标记为客户端组件。
- 是否在服务端模块顶层执行了依赖 DOM 的逻辑。
- 是否使用了同一份 Highcharts 实例。
- 是否将
@highcharts/react与旧的highcharts-react-official混用。
官方参考:

161

被折叠的 条评论
为什么被折叠?



