小程序开发踩坑汇总

前言

因为业务功能模块的需求,很多坑基本上都需要踩,比如引入第三方组件 vant, 引入 canvas,以及分包的问题。开发的环境是基于 Taro + Dva,外加魔改的一些配置

正文

真机调试问题

首先是在真机测试的时候,会出现之前的数据还遗留,或者说真机扫码开发者二维码一直在跳转没有进入页面。

这种问题一般是缓存和网络问题。

解决方案:

去真机把小程序从微信上删除,重新开发者工具的扫码入口进入

小程序预览,真机扫描无法正常请求接口,保证两者的 wifi 连接同一个即可。

canvas 引入

一般来说,按照官方文档是不够的,还得看 issue,看了也是不够的。因为还得自己处理引入后引发的问题。

微信版 canvas 官网: https://github.com/ecomfe/echarts-for-weixin

首先引入就是把 ec-canvas 这个文件夹下载过来放到自己的公共组件下

http://img.haoqiao.me/1585656093145.jpg

然后自己去官网定制 echarts.js, 记住不要选压缩。

在官网定制时不能勾选代码压缩,下载源文件后去专业的压缩网站压缩代码,再导入工程目录

压缩完成后下载替换文件下的同名文件。

之后要去 config/index.js 加配置

mini: {
  ...
  compile: {
      exclude: [
          path.resolve(__dirname, '..', 'src/components/ec-canvas/echarts.js')
      ]
    },
}

主要作用就是防止编译的时候再去编译它导致报错。

这时候工作只完成了一半,接下来是如何使用

在组件中引用

import * as echarts from '@components/ec-canvas/echarts';

因为是基于 Taro 开发的,因此还需要在组件配置中加上引用第三方组件的配置

usingComponents: {
      'ec-canvas': '../../../../../../components/ec-canvas/ec-canvas'
}

state 里保存一个 ec 变量

this.state = {
      ec: {
        onInit: initChart
      }
    };

initChart 作为外部函数这么写

function initChart(canvas, width, height) {
  chart = echarts.init(canvas, null, {
    width: width,
    height: height,
    devicePixelRatio: 2 // 设置高清 对高分屏所做的优化,如果不是 2 倍的话显示的效果不会那么清晰
  });
  canvas.setChart(chart);

  const dataAxis = [
  ];
  const data =
  ];
  const yMax = 500;
  const dataShadow: any = [];

  for (let i = 0; i < data.length; i++) {
    dataShadow.push(yMax);
  }

  const option = {
   ...
  }
  chart.setOption(option);
  return chart;
}

需要特别注意,默认的 devicePixelRatio 是 1,导致在高清移动屏上看到的效果非常模糊。需要设置为 2.

最终引用

<ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" ec={this.state.ec}></ec-canvas>

基本上可以跑起来。

图片

引入成功后也会发现一个问题就是微信原生 canvas 层级最高问题,遮挡底部悬浮菜单和弹窗。也就是我们弹个 modal 都会发现被遮挡。

这里有种做法是启用 echart 的保存图片功能,将绘制完成的 canvas 保存成图片。

const ecComponent = this.$scope.selectComponent('#mychart-dom-bar');
if (!ecComponent) {
return;
}

ecComponent.canvasToTempFilePath({
success: res => {
this.setState({ img: res.tempFilePath });
},
fail: res => console.error('canvasToTempFilePath', res)
});

但这种做法会失去交互性。

我采用的做法是全局设置状态,当弹窗等等有遮罩的动作,设置一个标志,如果出现这个标志,就把图表用骨骼组件代替。当然也可生成一张图然后代替。

核心思路就是把 canvas 从组件中暂时隐藏。

当然,当你一旦打算引用了 ecchart, 那么必定会遇到预览 500k 限制的问题。

这个问题只能通过分包来解决。

分包

分包策略基本上官方文档都有

https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/independent.html

主要原则,分包里别调用主包的内容,然后该提到公共组件库的都题到公共组件库。

简单贴个配置

config: Config = {
    pages: ['pages/index/index'],
    subPackages: [
      {
        root: 'packageOrder',
        name: 'packageOrder',
        pages: ['index', 'confirm/index']
      },
      {
        root: 'packageSetting',
        name: 'packageSetting',
        pages: ['index', 'myBill/index', 'feedback/index']
      }
    ],

http://img.haoqiao.me/1585656976960.jpg

但是即使你分包成功,有时候还是主包过大,不让你用开发者预览功能,这个时候需要自己进行排查。

主包文件过大终极方案

首先该压缩的压缩,该抽公共的抽公共,然后该分包分包。如果还是大,可以参考以下案例。

首先肯定是先利用工具排查一下哪个包有问题

利用分析工具 webpack-bundle-analyzer

http://img.haoqiao.me/1585657039295.jpg

有时候主包只有 1.8m 也会报错提醒文件包过大

可能是开启了增强编译

http://img.haoqiao.me/1585657090417.jpg

它会导致我们的文件莫名变得更大

http://img.haoqiao.me/1585657135584.jpg

通用解决方案:

1、分包

2、云函数

在云函数文件夹里 npm 安装这个包,在云函数里引用你要引用的包,然后使用包的方法,云函数返回处理结果即可最后在云函数文件夹上右键 -> 上传并部署:所有文件

3、利用 webpack 将公共引用提取出去 splitChunks commonChunks

屏蔽引入第三方 UI 库 ts 报错信息

http://img.haoqiao.me/1585657150145.jpg

类型“JSX.IntrinsicElements”上不存在属性“van-dropdown-item”

引入的标签不存在

解决方案 就是 在全局的 index.d.ts 加上

declare namespace JSX {
  interface IntrinsicElements {
    'van-dropdown-menu': any;
    'van-dropdown-item': any;
  }
}

其他

基本上小问题都可以 Google 到答案,如果 Google 不到,就去官方 GitHub 的 issue 里找,总会有人踩过坑。如果还没有,可以去小程序官方社区

https://developers.weixin.qq.com/community/develop/

提问等等。

Table of Contents