柴柴's TIL

webpack 打包页面中获取 ECharts 图表数据的方法

· 3 views ·

用 webpack 打包的前端页面(比如基于 ECharts 的监控大盘),通常无法在浏览器控制台直接访问图表数据。

问题:echarts 全局不可用

未打包的页面可以用 echarts.getInstanceByDom(el) 获取图表实例并读取数据,但经过 webpack 打包后:

typeof echarts // => "undefined"
window.echarts  // => undefined

原因:webpack 默认把模块作用域封闭,echarts 不挂载到 window,除非项目显式配置了 externalsProvidePlugin

问题:图表渲染在 Canvas

ECharts 默认用 Canvas 渲染,图表数据不在 DOM 里。即使遍历所有元素,也只能找到一个 <canvas> 标签,无法从中提取时序数据。

解决方案:注入 fetch/XHR 拦截器

在页面加载后、图表请求发出前,注入拦截器捕获 API 的原始 JSON 响应:

window.__chartData = {};

const _origFetch = window.fetch;
window.fetch = function(url, options) {
  const promise = _origFetch.apply(this, arguments);
  if (typeof url === 'string' && url.includes('your-api-domain.com')) {
    promise.then(r => r.clone().json().then(data => {
      if (!window.__chartData[url]) window.__chartData[url] = [];
      window.__chartData[url].push({ req: options?.body, res: data });
    }).catch(() => {})).catch(() => {});
  }
  return promise;
};

注入后触发图表刷新(重新选择时间范围或点击刷新按钮),再读取:

JSON.stringify(window.__chartData)

时机很重要

  • 必须在图表发起 API 请求之前注入拦截器
  • 如果页面已经加载完毕(初始请求已发出),需要主动触发刷新才能捕获新请求
  • XHR 拦截作为 fetch 的兜底,两者都需要处理

这个方案适用于所有基于 webpack 打包、通过 API 获取图表数据的前端页面,不局限于 ECharts。