TaroJS中引入echart踩坑血泪史

1,194 阅读5分钟

最近在使用TaroJS开发小程序过程中,需要绘制折线图功能。第一个想到的就是使用echart进行开发,毕竟echart有着使用简单,文档完善,物料库丰富等优点。但在使用过程中并不顺利,现将使用过程中的血泪史总结如下,供后续有相应需求的小伙伴参考

1、使用原生引入方法

作为一个有过echart使用经验的开发来说,使用起来 so easy,接到需求,第一反应就是安装echart库,创建DOM,然后

echarts.init(document.getElementById('main'))\

搞起。但很快就出现了第一个问题,控制台报错了,调试发现,getElementById获取到的并不是一个原生DOM,而是一个Taro Element。导致init注入失败。查阅小程序文档发现,小程序中并没有传统的 DOM 节点,因此采用原生注入的方式,行不通。

2、使用 ec-canvas

好在echart很贴心的为我们提供了小程序中使用的文档(echart文档)。但是我们使用的并非原生小程序,而是基于Taro的二次开发,好在各路大神都有成熟的开发经验供我们参考,这里提供一个当时查阅的文章(TaroEcharts-各种图表在Taro中的实践)。但按照文章操作下去,却并没有得到文章中的效果。而是会报一个

this.Chart.init is not defined\

调试发现,所使用的

usingComponents: {
"ec-canvas": "./ec-canvas/ec-canvas"
}\

注入自定义组件,并没有生效。经过排查,发现是因为之前由于微信授权接口调增,更新了Taro版本到 3.X,而 3.X 的版本,在架构上做了调整,导致通过ref获取到的是一个Taro Element从而无法执行子组件的内部方法。具体原因及解决方法,可参考(Taro内使用Echarts,以及升级taro3之后echarts失效问题处理)。踩着别人走过的路,终于在项目中,成功的渲染出了折线图,激动中...

3、使用echarts-taro3-react

虽然使用上面的方法,成功渲染出了图表,但是仔细查看代码发现,前人的解决方案中埋了一个隐形的炸弹。即

componentDidUpdate(nextProps) {
  const _this = this;
  setTimeout(() => {
    setChartData(chart, nextProps.chartData)
  }, 2000); // 异步获取到图表数据并更新
  }

这里通过了一个定时器延时的方式来处理初始化和数据渲染。这种延时方式是不安全的,一旦初始化时间过长,就会出错,而如果延时过长,则会导致体验变差。 经过多方查找,终于在Taro的物料市场中,找到了一个现成的解决方案。即echarts-taro3-react。(悔一开始没有仔细查找文档),文档中提供了简单稳定的使用方法。终于可以愉快的在项目中使用图表了。

4、项目拆包

但很快出现了新的问题,在完成表格渲染后,提交体验版时,出现了主包大于2M,无法上传的提醒,很明显,echart本身包的大小就高达 500Kb,引入之后,直接导致包的总大小,超出了2M。当然,解决起来也不难,微信文档很贴心的为我们提供了小程序分包文档。但这里有一个坑,即跟 tabBar 绑定的主页面,无法进行单独拆包。所以,需要协调产品即设计,将图表迁移至内页(暂未找到主页面的解决办法,如小伙伴们有解决方案,欢迎交流补充)。

但使用此方式拆包之后,如果在项目中多次使用了图标组件,那么恭喜你,又有一个新的坑等着你,你会发现虽然页面已经被单独拆分成了独立的包,但 echart 文件,却仍然被打包进了主包之中,导致主包超过2M。可见,当echart 被两个及以上各文件引用时,默认的打包便会将其作为公用文件进行抽离,而公用的文件,有被作为初次必须加载的文件放在了主包之中,从而导致了主包容量的增加。知晓原因,我们便有了解决办法,使用 webpack 的 splitChunk继续拆包吧。将 echart 文件单独打包成一个第三方文件。自定义webpack文档 为我们提供了引入 splitChunk 的方法。具体代码为

    // echartChunkName为echart路径
mini: {
  webpackChain(chain) {
    chain.merge({
      optimization: {
        splitChunks: {
          cacheGroups: {
            [echartChunkName]: {
              name: echartChunkName ,
              test: /[\/]node_modules[\/]echarts-taro3-react[\/]/,
              priority: 50,
            },
          },          
        },
      },
    });
  },
},

使用此配置之后,重新打包,会发现 echart 确实已经从公共文件 vendors.js 中抽离了出来,但主包的大小,却并没有减小,查询文档addChunkPages使用发现,还需要将第三方包进行单独注入,才可以让其真正脱离项目主包。那么加上以下配置

    addChunkPages(pages, pagesNames) {
      pages.set('pages/chart/pageA/index', [echartChunkName]);
      pages.set('pages/chart/pageB/index', [echartChunkName]);
    }

注意,建议将所有包含 echart 的文件页面放入同一个目录包中,以实现 echart 包的复用。注意,这里有个巨大的坑,及关于 echartChunkName 的设值,必须将其设置为跟分包相同目录之下,对以上示例即应设置为 pages/chart/echart 否则 echart 大小让然会被计算如主包之中,addChunkPages 不生效。至此,重新打包项目,会发现 echart 文件代码, pageA 代码,pageB代码均被打包到一个独立的文件之中,主包的大小也终于讲到了2M一下。大功告成。

5、其它小坑

在调试过成功,出现过一个奇怪的现象,即在开发者工具中,当图表绘制完成后,会脱离文档流,不管是页面滚动,还是通过调试工具删除所有节点。渲染完的图表都岿然不动。但后来在真机上进行调试则不存在这个问题。后面重启后开发者工具上也莫名恢复正常了(盲猜可能是跟电脑性能或者开发者工具缓存有关,还是重启大法好)。

还有在同一个页面中插入多个表格,则需要保证EChart标签中的canvasId值唯一,否则将无法渲染多个。