小程序瘦身之旅

2,068 阅读5分钟

背景

在 web 开发场景,减少代码体积虽然是性能优化的一个方向,还没到锱铢必较的程度。但是在小程序场景,由于代码包上传阶段限制了主包 **2M **和总包 20M,超过就会面临无法发版的风险,代码包体积的优化就变得特别重要了。

taro小程序的优缺点

优点

  • 多端开发
  • H5无缝切换小程序、上手快

缺点

  • 升级成本较高
  • 高版本框架不稳定,跳到坑里
  • 有些功能框架实现不了,只能用原生(wx.getUserProfile)
  • 包体积相对过大

永享贷小程序(taro版)代码依赖分析

不包含三方插件,总包代码体积1.7M

image.png

永享贷小程序(原生)代码依赖分析

不包含三方插件,总包代码体积1.08M,相比taro小程序体积减少了36%

image.png

常用瘦身方式

1、依赖分析优化无依赖文件

  • 移除未引用的页面、组件和其他文件
  • 移除demo文件夹

image.png

小程序包体积提示: 使用该方法预计节省体积70kb

2、避免使用本地资源

  • 除了兜底图片(tabBar),其他都尽可能使用 url 的方式
  • 由于 base64 图本质上是将信息编码成长字符串,也会占用很多空间,不建议使用

image.png

小程序包体积提示: 使用该方法预计节省体积500kb

3、过滤本地不必要上传文件

本地可以忽略*.vscode .gitignore .README .prettierrc package-lock.json wx.d.ts等文件,缩小上传后的小程序包大小 image.png

小程序包体积提示: 使用该方法预计节省体积200kb

4、小程序瘦身工具(微信官方文档)

文档链接 image.png

小程序包体积提示: 使用该方法预计节省体积未知

5、代码压缩及编译

微信开发者工具本地设置

  • 上传代码时自动压缩样式
  • 上传代码时自动压缩混淆
  • 开启增强编译(增强ES6转ES5的能力)

image.png

小程序包体积提示: 开启压缩前上传1644kb,开启压缩后上传1016kb,开启增强编译后上传1036,体积减少37.5%

6、整理console.log

  • 及时移除开发调试用 log(gulp移除:正在调研)
  • 信息类 log 约定长度更短的格式
  • 小程序正式版一键关闭log
// app.js
//一键开启、关闭log,正式版不输出日志
console.log = __wxConfig.envVersion !== 'release' ? console.log : () => {};

永享贷小程序包体积提示: 使用该方法预计节省体积5-10kb

7、良好的编码策略

  • 优化冗余代码
  • 全局样式放到app.wxss中
  • 简化dom节点

8、借助小程序运行评分

image.png

优化部分代码,从而间接提高性能

X、分包加载

某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。完成分包后有以下优势:

  • 将相对独立的页面和组件拆分到分包,可以解决主包体积受限问题
  • 主包加载时间减少,从而提高小程序启动性能

分包也有以下注意事项:

  • 启动页和TabBar 页面必须放在主包里
  • 分包需用到公共JS 脚本必须放在主包里
  • 分包之间资源和方法不能相互引用(packageA 无法 require packageB JS 文件)

小程序分包配置方法、分包预下载

{
  "pages": ["pages/index"],
  "subpackages": [
    {
      "root": "important", // 分包根目录
      "pages": ["index"],
    },
    {
      "name": "hello", // 分包别名
      "root": "path/to",
      "pages": ["index"]
    }
  ],
  "preloadRule": {
    "pages/index": {
      "network": "all",
      "packages": ["important","hello", "sub3"]
    }
  }
}

分包初步方案实现效果: image.png

小程序包体积提示:总包1.29M 主包1.09M,初次加载提交减少了15%

疑问1:npm包为啥都在主包里面? 疑问2:为啥有重复的npm包?

**疑问1解决方案:分包将package.json也分离,实现demo **developers.weixin.qq.com/s/M1IuBSmW7… npm包分包构建 image.png 疑问2解决方案:自定义 node_modules 和 miniprogram_npm 位置的构建 npm 方式

1、npm默认构建方式: 小程序 npm 包会直接拷贝构建文件生成目录下的所有文件到 miniprogram_npm 中

// 构建前
|--node_modules
|    |--testComp // 小程序 npm 包
|    |    |--package.json
|    |    |--src
|    |    |--miniprogram_dist
|    |         |-index.js
|    |--testa // 其他 npm 包
|         |--package.json
|         |--lib
|         |    |--entry.js
|         |--node_modules
|              |--testb
|                   |--package.json
|                   |--main.js
|--app.json

// 构建后
|--node_modules
|--miniprogram_npm
|    |--testComp // 小程序 npm 包
|    |    |-index.js
|    |--testa // 其他 npm 包
|         |--index.js // 打包后的文件
|         |--miniprogram_npm
|              |--testb
|                   |--index.js // 打包后的文件
|                   |--index.js.map
|--app.json

2、自定义构建 npm 方式

// project.config.json 新增配置如下
"setting": {
  "packNpmManually": true, // 开启自定义 node_modules 和 miniprogram_npm 位置的构建 npm 方式
  "packNpmRelationList": [
    {
      "packageJsonPath": "./src_node_modules_1/package.json", // 表示 node_modules 源对应的 package.json
      "miniprogramNpmDistDir": "./miniprogram/" // 表示 node_modules 的构建结果目标位置
    },
    {
      "packageJsonPath": "./src_node_modules_2/package.json",
      "miniprogramNpmDistDir": "./miniprogram/sub_package"
    }
  ]
}

// 构建前
├── miniprogram
│   ├── app.js
│   ├── app.json
│   ├── index
│   └── sub_package
│       └── sub_package_page
├── project.config.json
├── src_node_modules_1
│   ├── node_modules
│   └── package.json
└── src_node_modules_2
    ├── node_modules
    └── package.json

// 构建后
├── miniprogram
│   ├── app.js
│   ├── app.json
│   ├── index
│   ├── miniprogram_npm // 由 src_node_modules_1/node_modules 构建得到
│   └── sub_package
│       ├── miniprogram_npm // 由 src_node_modules_2/node_modules 构建得到
│       └── sub_package_page
├── project.config.json
├── src_node_modules_1
│   ├── node_modules
│   └── package.json
└── src_node_modules_2
    ├── node_modules
    └── package.json

利用自定义构建npm包解决疑问2,示意图如下

image.png=>image.png=>image.png

分包优化方案实现效果:image.png

小程序包体积提示:初步方案总包1.29M 优化方案总包1.08M,包体积减少16%

过滤npm包后的总包情况 image.png

总结

image.png

其他常见小问题

1、小程序缓存隔离策略

同一个微信用户,同一个小程序 storage 上限为 10MB。storage 以用户维度隔离,同一台设备上,A 用户无法读取到 B 用户的数据;不同小程序之间也无法互相读写数据

// 没有必要加缓存字段前缀了
const PKGNAME = 'yxd';
const getKey = (key) => {
  return `${PKGNAME}_${key}`;
};
export default {
  STORAGE_OPENID: 'openid', // 小程序openid
  STORAGE_USERID: 'userid',
};

2、getLocation增加调用频率限制

从基础库2.17.0版本起(预计发布时间2021.4.9),将对getLocation接口增加频率限制,包括:

  • 在开发版或体验版中,30秒内调用getLocation,仅第一次有效,剩余返回fail。
  • 正式版中,为保证小程序正常运行同时不过度消耗用户电量,一定时间内(根据设备情况判断)调用getLocation,仅第一次会返回实时定位信息,剩余返回与第一次定位相同的信息。

未做好兼容调整可能会影响用户体验,请开发者尽快适配。参考链接