# 1. 背景
工具是生产力的基本,也是提升研发效能的关键。工具是一个个点,当把这些点封装好、关联好,串联起来,就构成了基础设施。团队需要持续不断的沉淀这些工具。
项目由web项目转为跨端项目过程中,积累了一系列工具,这里对一些核心工具进行下总结,主要包括原理、用法、效果等方面。
从宏观上说,这些工具解决的问题包括:
- 瓶颈问题、卡脖子问题,不解决就无法继续进行,比如JS分发、组件分发,如果不解决,就无法满足小程序主包2M的限制,无法预览、上传、上线。
- 自动化相关,大幅减少工作量,以更优雅、更稳定的方式,替代手动改代码,提高效率
从技术类别上,这些工具类型分为:
- Eslint插件
- Webpack Loader
- Webpack Plugin
- 脚手架工具,可视为node脚本的集合
- CI相关
# 2. 工具
# 2.1. JS分发
JS分发和组件分发客观来说,是相对复杂的插件。
# 2.1.1. 背景
由于uni-app对JS文件的打包策略并不完善,会将多个分包使用的JS都放到主包中,这会让主包变得特别大。因此需要将只有分包使用的JS文件转移到分包中。
# 2.1.2. 原理
总体分为两步,第一步是先收集要移动的文件,第二步是真正移动。
收集过程是从 compilation.modules 过滤出vue文件,就是一个个module,然后获取这些 module 的 chunks,找到这些 chunks 对应的分包,如果有分包在使用,但是主包没在使用,就把它放入 moveFiles 中。
移动 module 过程如下。遍历 modules,如果某个 module 存在于 moveFiles 中,调用 module.getChunks 获取它的所有 chunks,如果只有 common/vendor 中包含这个 module,说明这个需要被放到分包中,并将 common/vendor 中的移除。
# 2.1.3. 效果及扩展
JS分发插件使用后,主包大小减少了0.51M。
除了上面自动化的移动JS外,还实现了移动指定JS文件到指定分包的功能,扩展了插件的使用场景,可以让主包更小。
# 2.2. 组件分发
# 2.2.1. 背景
组件分发的灵感来自于uni-app源码中的提示,“将只有分包使用的组件移动到分包中”。
项目的一些公共组件,比如local-component、component中vue文件,会被打包到主包中,因此这里需要将只有分包使用的组件移动到分包中,但是如何在不改动项目架构的情况下实现这一功能呢?
# 2.2.2. 原理
总体步骤如下:
- 生成组件的基本相互引用关系
- 构建组件所有引用关系图
- 拉平上述组件关系
- 逆向获取使用一个组件的所有分包
- 根据组件使用的分包进行移动、删除主包内容等
# 2.2.3. 效果及扩展
使用组件分发插件后,主包大小减少了 2.17 M。
为了让插件更加灵活,可以适应不同项目,提供了几个配置选项:
- 最大分包使用数目 maxUseTimes
- 对一个组件,如果使用它的分包多于 maxUseTimes 时,就不再处理
- 禁止移动的组件列表 disableList
- 如果 disableList 中包含组件的路径和名称匹配到了,就不再处理
使用前:
使用后:
# 2.3. Eslint插件
开发了Eslint插件eslint-plugin-pmd
,可以一键转化不符合跨端规范的代码,包括:
禁止从js文件中加载Vue组件。 由于uni-app仅支持vue文件组件,并不能识别从js引入再导出的组件,所以这里需要自动转化。
禁止在vue的template中用+号转换字符串为数字 uni-app不允许
+str
语法,这里自动识别并自动转为parseInt(str)
禁止在vue模板中使用复杂的key 对于字符串拼接
:key="
hold+ index"
这种key会及时提示错误
# 2.4. 全局组件插入loader
对于一些所有页面都在使用的组件,用loader的方式自动注入,提升了效率,也减少了出错的可能。
# 2.5. page-meta插入loader
微信小程序原生支持rem,但是需要插件page-meta标签,这里也是用loader自动注入。
# 2.6. 替换web端组件
一些web端的组件也会被打包进小程序的产物中,因为小程序模式下无法开启tree-shaking。因此这里需要用工具将一些没用的组件消除掉。
替换一个文件有两种方式:
- 将引入文件的地址替换,比如import { Button } from 'vant',可以将vant转为一个另一个文件,import { Button } from 'fake-comp';
- 加载文件时,用新内容替换,对于上面的例子,就是加载vant时,直接替换掉。
对于三方库,用的是第1种方式,对于本地文件,用的是第2种方式。
# 2.7. 懒加载的兼容
web用的是lazyload这个三方库,而小程序自带lazyload属性,所以实现了一种根据编译环境,自动选择合适的懒加载方案的loader。
# 2.8. 调试工具
实现了小程序打包产物中自动注入构建信息的工具,方便查看:
- 最后一次commit信息
- 构建环境
- 版本是否被覆盖、是否是最新的
- 当前是测试环境还是线上环境
# 2.9. 基于摩斯密码的加密
实现了基于摩斯密码的加密方案,可以在小程序中隐藏对应的h5路由信息,方便开发者调试定位问题。
# 2.10. 路由hook
用hook的方式扩展uni-simple-router的路由模式,可以做到不改代码,也可以保留h5的功能多样性。
# 2.11. CI相关
实现了微信小程序和qq小程序的自动构建、自动上传、自动预览的功能,主要解决了以下痛点:
构建时间长,流程繁琐
外部开发人员无法预览
本次CI功能点如下:
- 自动进行uni-app打包,打包两份:test和release环境
- 将打包产物自动上传
- 自动预览、生成图片
- 将预览图片上传到腾讯云
- 发送构建通知、腾讯云图片地址到企业微信
下面是一些相对于其他CI的优化点:
- 多环境区分
- 对于开发版,同一个开发者只能保留一份,当我们既想看测试环境,又想看正式环境时就捉襟见肘了。
- 借助小程序ci,对多个环境用不同的机器人,这样就不会覆盖了。
- 配置驱动
- 由于小程序ci机器人范围有限(1-30),所以只能手动维护,让其重复利用。
- 这里我让项目每个分支每个环境分别对应一个机器人,当一个分支废弃后,这个机器人就可以释放给其他分支使用。
- 同时其他配置项也可以统一保管起来,比如腾讯云密钥、小程序密钥等,方便维护
- 自动重试
- 有时候上传或者预览会失败,可能是环境问题,也可能是多个流水线同时上传会冲突,因为需要增加自动重试功能。
- 并行提速
- 上传和预览是可以同步进行的,这样可以节省一些构建时间。
- canvas绘图
- 小程序ci默认提供的图片只有二维码,笔者用canvas将一些构建信息和二维码绘制到一张新图上,方便定位和查看。
- 绘制的信息示例:
- 版本号:1.0.5
- 提交者:CI机器人5
- 环境:test
- 分支:release
- 构建时间:2022-10-19: 09:36:37
- 最后提交:lee - 修复page
- 二维码
目前,CI流水线日均构建30+次,每次构建时间6min左右,每日可节省工时180min+。
# 3. 工程化
由于loader的机制接近于黑盒子,为了保证工具的稳定性,需要用完善的测试用例覆盖,其他工具也是如此。
这里我将上述的loader、plugin抽离出来,并用ts+jest+rollup重构,单独发了npm包uni-plugin-light,好处是:
- 方便其他项目接入
- 核心方法必须通过单元测试,提高了工具的可用性,减少了bug率
- 方便扩展
# 4. 其他工具
除了上述跨端工具外,这里也简单介绍下一些其他实用工具:
- eslint-plugin-light,一行代码完成eslint配置
- 开源治理日报机器人,每日提醒代码规范、代码安全问题
- TAM日报,每次发送项目PV、UV、错误率、性能数据,方便开发人员查看
- 公共库自动打Tag、自动升版本,并发送changelog到企业微信群中
- 七彩石配置自动同步COS,方便使用
# 5. 总结及后续规划
在日常开发中,开发了一系列工具,解决了一些针对性的问题,提升了效率。
除了工具链外,前端开发中另一个重要的部分是组件库,由于分工过细、赶需求等,规范的组件库一直没有沉淀下来,后面会加强此方面的建设,构建高可用、灵活的组件库。
← 赛程树样式重构 Vite打包产物分析 →