背景

目前全量 G2 3.x 加载之后,大概的包大小在 800kb+,按需加载仅加载一个 Line 图,大概在 450kb 左右。

image.png

这个对比 echarts 来看,差距还是挺大。主要体现在:

  1. 按需打包的类别
  2. 包大小(折柱饼:360kb 左右)
  3. 定制打包工具

实现

加载类别

  • SVG & Canvas

增加一个 registerEngine 的 API,然后按需引入 SVG 和 Canvas 能力。

  • Geometry

通过 registerGeometry 的方式 load 图形。可以分成 line、Interval、point 等多个。

  • ComponentPlugin

通过 registerComponentPlugin 的方式 load 组件及其 Controller。可以分成为 axis、legend、tooltip、annotation 等多个。

  • Theme

通过 registerTheme 的方式加载主题。可以分成为 antv、dark 两类主题。默认至少选择一个主题。

  • Facet

通过 registerFacet 的方式加载分面。可以分成为 rect、tree、circle 等多个。

  • Action、Interaction

TODO: 通过 registerAction、registerInteraction 的方式即在交互,分可以分成为:xxx,yyy 等。

  • Coordinate

通过引入 @antv/coord/lib/factory,然后调用 registerCoordinate 的方式加载 coordinate。可以分成为 rect、polar、helix 三个。(这个好像并不能节省多少大小)

  • Adjust

通过引入 @antv/adjust/lib/factory,然后调用 registerAdjust 的方式加载 adjust。可以分成为 stack、dodge、jitter、symmetric 四个。

减少包大小

  • antv/util 按需引入(-10kb)
  • scale 去除 moment 依赖(-100kb)

代码实施

  • core.ts

全部引入空壳子,并 export 所有的 register 类 API。

  • index.ts
  1. import { registerGeometry } from './core';
  2. registerGeometry('line', Line);

相当于 core 导入的是最小量的包大小,index 导出的全量的包大小。两者在导出的 API 上是一致的。

上层按需引入

比如 g2plot 绘制一个折线图,怎么样让这个包大小最小。

  1. // 使用 G2/core 壳子
  2. import { Chart, registerGeometry, registerComponentPlugin, registerCanvas } from '@antv/g2/lib/core';
  3. import Line from '@antv/g2/lib/geometry/line';
  4. import Axis from '@antv/g2/lib/component/axis';
  5. import Tooltip from '@antv/g2/lib/component/tooltip';
  6. import G from '@antv/g-canvas';
  7. // 按需注入
  8. registerCanvas('canvas', G);
  9. registerGeometry('line', Line);
  10. registerComponentPlugin('axis', Axis);
  11. registerComponentPlugin('tooltip', Tooltip);
  12. // 创建折线图,后面的代码没有任何区别
  13. const chart = new Chart({
  14. container: 'container',
  15. width: 600,
  16. height: 500,
  17. renderer: 'canvas',
  18. });
  19. chart.data(data);
  20. chart.line().positon('x*y');
  21. chart.render();

在线定制工具

  • meta 维护

全部的可 register 内容,分类信息,名称,源码路径等;通过这个 meta 信息来渲染出打包工具的页面。

  • 打包 entry 文件

根据页面上选择的包,然后自动生成 entry.js 文件。

  1. export * from '@antv/g2/lib/core';
  2. import { registerGeometry } from '@antv/g2/lib/core';
  3. import Line from '@antv/g2/lib/geometry/line';
  4. registerGeometry('line', Line);
  5. // ... 其他的 register 内容

备注:entry 文件改成使用 es5 编写,减少 webpack loader。

  • 打包

使用 webpack 打包,使用 entry.js 作为打包入口,最终生成一个 g2.min.js 文件。

要不使用 nodejs server 的方式做成在线,要不使用 electron 做成本地工具。可以到时候找一个外包同学来帮忙做了。

预测包大小

预测,可能偏差很大打包空壳文件,大概 250kb 左右,打包折柱饼,大概在 350 kb 左右。到时候再看 bundle 分析图再做进一步细节优化。