上周帮朋友看他刚上线的小程序,反馈说部分安卓机上日期选择器点了没反应,iOS 却一切正常。我第一反应不是翻他的业务代码,而是先问了两件事:出问题那台手机上微信小程序基础库版本是多少,你在管理后台设置的最低基础库版本又是多少。他愣了两秒,说这两个东西从来没关注过。这个反应太典型了,很多人写小程序的第一年里,基础库都是一个"看不见"的存在,直到某个组件在特定机型上莫名其妙失效,才第一次听说这个词。
微信小程序基础库,说白了就是运行你小程序代码的那一层"底座",它由微信客户端内置,负责把 wx.xxx 这类调用翻译成真正的系统能力。你写的页面、组件、API 调用,全都跑在它上面。基础库版本决定了哪些 API 能用、哪些组件属性生效、渲染引擎怎么处理布局。它跟微信客户端版本绑定,也跟你的项目配置绑定,三个地方任何一处没对齐,就可能出现"我本地好好的,用户那边就是不行"的经典事故。
这篇内容我打算把基础库这件事从头到尾讲清楚:它到底是什么、版本号怎么读、用户都在什么版本、后台和工具里分别在哪里设置、代码里怎么写兼容、出问题怎么排查。适合刚接触小程序开发的新手,也适合写过一段时间但一直没系统梳理过版本兼容的老手。看完你至少能明白一件事:为什么你的代码在线下能跑,用户一升级微信就翻车。
1. 基础库到底是个什么角色,三层结构先讲透
很多人把基础库和微信客户端混为一谈,结果排查问题时方向就错了。这两者其实是分开的:微信客户端是那个 App 本身,基础库是随客户端分发、但独立演进的运行环境。它们的更新节奏不一样,同一版本的微信客户端在不同机型、不同灰度批次里,内置的基础库版本也可能不同。理解了这一点,你才能明白为什么同一个用户上一秒还能用,重启一次微信之后就变了。
1.1 小程序代码、基础库、微信客户端的三层关系
我把这三层关系比作"应用软件、操作系统、硬件"会更直观一些。你写的 WXML、WXSS、JS 是应用软件;基础库相当于操作系统里那一层运行时和驱动;微信客户端是硬件加整机。你调用 wx.getLocation,基础库负责把它翻译成客户端能执行的指令,客户端再去调用系统的定位能力,最后把结果一层层往回传。
这种分层带来一个很实际的后果:你代码里写的 API 名字,在低版本基础库里可能根本不存在。不是报"参数错误",而是直接提示某个函数不是一个函数。因为那层底座上压根没有这个函数。所以每次遇到这类报错,第一件事应该是查这个 API 是哪个基础库版本开始提供的,而不是去改业务逻辑。
再往细里说,基础库还分成逻辑层和渲染层。逻辑层跑你的 JS,渲染层负责 WXML 的排版和绘制。两层的通信在早期版本里是异步的,这就是为什么频繁 setData 会卡。后来的版本里做了不少优化,比如同层渲染、按需注入、初始渲染缓存,这些能力全都跟基础库版本强绑定。你项目里开启的这些优化开关,在低版本基础库上要么被忽略,要么行为不一致。
还有一个容易忽略的点:开发者工具里的基础库是你自己选的,不等于用户手机上装的。工具里可以随便切到最新版本做开发,但如果后台最低版本设得太低,或者用户微信没更新,真机上跑的还是老版本。这个落差就是绝大部分"模拟器正常、真机异常"问题的源头。
1.2 版本号怎么读,1.1.0 这串数字里藏着什么
基础库版本号是标准的语义化三段式:主版本号、次版本号、修订号。举几个真实的例子,2.30.0、3.0.0、3.7.12 这种。读法其实很简单:第一位是大的架构或能力变更,变动频率最低;第二位是功能迭代,新 API、新组件属性基本都在这里加进来;第三位是修 bug 和小修补,一般不需要你特别关心具体数字。
判断"某个能力我能不能用",看的几乎都是第二位。比如分包异步化、按需注入这类能力,都是 2.x 中间某个次版本才出现的。官方文档每个 API 页面右下角都会标注"基础库 x.x.x 开始支持",这个数字才是你真正要记住的。我在做新项目时会专门建一个注释文件,把项目里用到的所有"有版本门槛"的 API 和属性列出来,后面做兼容判断时直接查表,比每次翻文档快得多。
还有一个概念叫"最低基础库版本",这是你在管理后台可以主动设置的一个值。它表达的意思是:低于这个版本的用户,微信会提示他升级客户端,或者直接不让进入小程序。这个值设得越高,你越能放心用新 API,但会流失一部分老设备用户。设低了覆盖面广,但你的代码得写一大堆兼容分支。这就是后面要讲的核心取舍。
顺带提醒一句,不要用 SDKVersion 字符串直接做大小比较。像 "2.9.0" 和 "2.10.0",按字符串比 "2.9.0" 更大,实际却是更旧。要么用 wx.canIUse,要么把版本号拆成数字数组再逐位比。这个坑我在早期项目里踩过一次,导致兼容逻辑判断反了,上线后才发现。
1.3 同一段代码在不同手机上表现不一样的根本原因
安卓和 iOS 的差异,一部分来自系统本身,一部分来自基础库的渲染实现。iOS 上小程序的渲染层用的是基于 WebKit 的方案,安卓上早期是另一套,后来逐步统一。这就解释了一个非常常见的现象:iOS 上滚动顺滑的页面,安卓上会出现滚动卡顿或者滚动穿透;而安卓上正常的 fixed 定位,iOS 上偶发闪烁。
举个具体例子,scroll-view 这个组件。它在 iOS 上的滚动行为和安卓就不完全一样。当 scroll-view 内部放了一个自定义组件,而这个组件内部又用了一套自己的滚动逻辑时,iOS 上可能出现手势冲突,滚动到一半突然停住或者反向。这类问题你改业务代码几乎无效,本质是渲染层和基础库版本的配合问题。
再比如 uni-datetime-picker 这类第三方组件,把它放进 scroll-view 里,在部分 iOS 机型上点击日期弹层会失效。原因是弹层依赖的定位和事件冒泡在 scroll-view 的滚动容器里被拦截了。解决办法通常是把 picker 提到 scroll-view 外面,或者给它加一层 cover-view,或者在特定基础库版本上改用原生的 picker 组件。这些都是"版本 + 平台 + 组件层级"三者叠加出来的问题。
所以排查这类"玄学问题"的顺序应该是:先确认基础库版本,再确认平台,最后才去看代码逻辑。顺序反了,你会在业务代码里浪费大量时间。
2. 先摸清你的用户在跑哪个版本
谈兼容之前,得先有数据。凭感觉猜用户版本,跟闭着眼睛调参数没什么区别。微信给开发者留了一个版本分布面板,但很多人从来不看,或者看了不知道怎么用。这一节讲怎么读这个面板,以及怎么把它变成具体的版本决策。
2.1 后台的版本分布面板怎么读
在小程序管理后台的"数据"相关入口里,可以找到基础库版本分布和客户端版本分布。它给你的是一段时间内的用户占比。我一般会关注三个数:排名前三的版本、最低那个版本的用户占比、以及最新版本的用户占比。
如果你的用户里有一大批停在两三个大版本之前,那说明这群人微信更新不积极,很可能是中低端安卓机用户。这部分人你既不能轻易放弃,也不能为了他们把整个项目的新特性都砍掉。反过来,如果你的用户几乎都是最近一两年的新版本,那你完全可以大胆把最低版本调高。
还有一个细节:版本分布是动态的。微信每次发新版本,一段时间内会出现一波版本迁移,比例会明显变化。所以这个面板不要只看一次,重大版本发布前后各看一次,心里才有数。我习惯在每个大版本发布后两周再回看,这时候灰度基本覆盖完了,数据比较真实。
2.2 覆盖率和开发成本的那笔账
把最低基础库版本往上调,本质上是用一部分用户换开发效率。这笔账怎么算,我给你一个思路。
假设你当前设的最低版本是 2.10.0,想把某个能力用上,需要提到 2.25.0。后台显示低于 2.25.0 的用户占 3%。这 3% 的用户里,有一部分其实能通过升级微信解决,真正卡死的可能只有 1% 左右。如果你的业务是面向年轻人的工具类产品,这 1% 大概率可以接受;如果是面向下沉市场的线下扫码场景,这 1% 可能就很要命。
反过来,如果你的项目体量很小,用户总量本来就少,砍掉 1% 意味着直接掉用户,那就得老老实实写兼容分支。我的经验是:先看这 1% 值不值,再看兼容代码要写多久。如果兼容分支只需要二三十行,那写就是了;如果需要重写整个交互流程,那就果断提版本,用公告或者引导页提示低版本用户升级。
这里还有个容易被忽略的成本:兼容代码本身会长期存在,每次改相关功能都要考虑两条路径,维护成本是持续付出的。所以"能提版本就不写兼容"这个原则,在维护期长的项目里往往更划算。
2.3 一套我自己在用的选版策略
下面这个表是我这些年总结的选版参考,实际用的时候结合自己后台数据调整。
| 项目类型 | 建议最低基础库 | 理由 |
|---|---|---|
| 内部工具、员工端 | 直接最新或降一个大版本 | 用户可控,能要求统一升级微信 |
| 面向年轻人的 C 端产品 | 近一年内的稳定版本 | 用户更新意愿高,能吃到新特性 |
| 线下扫码、老年用户多 | 两到三年前的老版本 | 设备老旧,覆盖优先于体验 |
| 直播、音视频、小游戏 | 新版本 + 明确引导升级 | 实时音视频能力对版本依赖极强 |
| 电商、工具类 | 折中,重点 API 做兼容 | 覆盖面优先,少量新能力做兜底 |
这张表不是标准答案,只是一个起点。真正的决策一定要回到你自己的版本分布数据上。我见过有人直接照搬网上的建议,结果自己的用户有 20% 在低版本,上线后投诉一片。
提醒:调整最低基础库版本会影响用户能否进入小程序,属于影响面较大的配置,改之前最好先看完整分布数据,改之后盯几天的进入率和投诉。
3. 基础库版本到底在哪里改
"基础库版本从哪设置"这个问题在网上被问得特别多,答案其实不止一处,而且每一处的作用完全不同。很多人只知道开发者工具里能切,不知道后台还有一个真正面向用户的设置。这一节把三类入口讲清楚,顺便带上 uniapp 和小游戏这两个高频场景。
3.1 开发者工具:本地调试版本随手切
微信开发者工具里,打开项目后点右上角的"详情",找到"本地设置",里面有一项"调试基础库版本"。这个下拉框决定的是模拟器和真机预览时用的基础库版本。它的作用是让你在不改任何线上配置的前提下,快速验证低版本下的表现。
我的做法是固定两个档位来回切:一个是我在后台设置的最低版本,一个是最新版本。每次写完涉及新 API 的功能,先在最低版本档位跑一遍,确认没有报错,再切回最新版本。这样能在开发阶段就发现问题,而不是等用户反馈。
这里有个坑要提醒:工具里选的基础库版本,和你手机上真机调试的版本不一定一致。真机调试时,基础库跟着你手机上的微信客户端走,工具里的设置不一定生效。所以凡是涉及版本兼容的验证,最终一定要在真机上、在目标机型上再确认一次,尤其是安卓中低端机。
还有一点,工具的版本列表会随工具更新,有些太老的版本可能已经不在列表里了。如果你确实需要验证一个很老的版本,可以手动下载历史版本的工具。这个操作不常用,但遇到疑难兼容问题时挺管用。
3.2 管理后台:设置最低基础库版本
这个才是真正面向所有用户的设置。在小程序管理后台的"设置"相关页面里,有一项"基础库最低版本"。设置之后,低于该版本的微信客户端在打开你的小程序时会被提示升级。这个设置的特点是需要提交审核生效,而且生效有延迟,所以要提前规划。
设置的时候,后台会告诉你当前各版本的分布情况,方便你判断影响面。我一般的操作流程是:先在开发者工具里把最低版本档位调成打算设置的值,跑一遍全量功能回归,确认没问题,再去后台提交设置。审核通过后,观察一到两天的进入率和用户反馈。
有个细节很多人不知道:这个最低版本和"用户手机的微信版本"是绑定的。也就是说,你设置了 2.25.0,但用户的微信版本对应的基础库是 2.20.0,那他就会被拦下来。这也就意味着你设置的版本越高,被拦的用户越多。所以不要盲目往高了设置,一定结合分布数据。
另外要提醒的是,这个设置和"小程序版本"是两回事。你发布了新版本代码,最低基础库版本不会自动跟着变,需要单独设置。我见过有人以为发了新版就自动提高了最低版本,结果新 API 在老机型上大面积报错。
3.3 uniapp 和 HBuilderX 项目里的两处配置
用 uniapp 开发的同学经常搞不清基础库到底在哪设。答案是:在 uniapp 侧,你只能设置调试用的基础库版本,真正面向用户的还是要去小程序后台设。uniapp 里这个配置在 manifest.json 的 mp-weixin 节点下,字段是 libVersion,取值一般是 "latest" 或者具体的版本号。
一个简化的配置片段长这样:
{ "mp-weixin": { "appid": "你的appid", "setting": { "urlCheck": false, "es6": true, "minified": true }, "libVersion": "latest", "usingComponents": true } }这里的 libVersion 只影响 HBuilderX 发行到小程序时的调试基础库版本,不会改变线上用户的最低版本。所以你用 uniapp 打包发布之后,还是要去后台设置最低版本,两件事不能互相替代。
发行流程上还有一点值得说:HBuilderX 里点"发行 - 小程序 - 微信",会生成一个 unpackage/dist 目录,然后用开发者工具打开这个目录上传。基础和正常的原生流程一致,只是多了一层编译。这个过程中,manifest.json 里的 libVersion 会带到生成的配置里,所以如果你在项目里把 libVersion 设得很新,上传时工具里也会默认用这个版本,容易造成"本地能跑、用户那边不行"的错觉。
3.4 小游戏和 Unity 导出方案的差异
小游戏的基础库设置和小程序不完全一样。小游戏的核心运行环境是同一套基础库,但它多了一层游戏引擎的适配。用 Unity 导出的小游戏,里面有一份适配层代码,这份代码对基础库版本有要求。如果用到了视频播放、音频播放这些能力,版本门槛会更明显。
比如 Unity 小游戏里做视频播放,通常走的是小游戏提供的视频相关接口。这些接口对基础库版本有明确要求。你如果在小游戏后台把最低版本设得太低,用户那边可能出现视频黑屏、音频不同步。排查这类问题时,先确认基础库版本,再看适配层版本,最后才是业务逻辑。
小游戏后台同样有基础库最低版本的设置入口,逻辑和小程序一致:设置后低版本用户会被拦截。所以小游戏项目在立项阶段就要想清楚目标设备范围,尤其是需要兼容老旧安卓机的项目,视频类能力要提前做降级方案。
4. 代码层面的兼容写法
配置层面的东西理清楚了,接下来是代码。就算你后台设置得当,也总有一部分用户处在边界版本上,代码里该有的兜底还是要有。这一节讲三个层面的写法:能不能用、不能用怎么办、以及渲染层的坑。
4.1 wx.canIUse 到底该怎么用
wx.canIUse 是最常用的能力探测方法。它的参数是一个"能力字符串",返回值是布尔值。用法分三类:判断 API 是否存在,比如 wx.canIUse('getLocation');判断组件属性是否支持,比如 wx.canIUse('button.open-type.contact');判断接口参数是否支持,比如 wx.canIUse('showToast.object.image')。
我通常写好一个小的工具函数,把常用的能力判断包一层,这样业务代码里调用更清爽:
function support(api) { return typeof wx.canIUse === 'function' && wx.canIUse(api) } if (support('getLocation')) { // 走定位逻辑 } else { // 提示用户升级微信版本 }这里有两个常见误区。第一个是把 canIUse 当万能,实际上它只能判断存在的 API,不能判断某个 API 在你的目标用户版本上行为是否正常。有些 API 在所有版本都存在,但低版本上参数支持不全,这种要结合版本号判断。第二个是在 canIUse 之前就调用了新 API,比如在页面初始化阶段直接用,结果代码执行顺序上探测还没跑就报错了。兜底逻辑要放在调用之前。
还有个细节:获取当前基础库版本可以用系统信息接口里的 SDKVersion 字段,新版 API 把系统信息拆分了,取版本信息的方式也有变化。所以在用 SDKVersion 做判断时,本身也要做一次存在性判断,否则在新旧版本混用的场景下会出问题。这个套娃式的兼容思路,写多了就有肌肉记忆了。
4.2 API 缺失时的降级实现
探测出能力缺失,接下来就是降级。降级的方式无非三种:用旧 API 替代、用 H5 或自绘方案替代、直接给用户一个友好的提示。
用旧 API 替代最典型的例子是分享和登录。老版本用旧接口,新版本用新接口,写一个分支就行。这类降级成本低,优先用这种方式。
用自绘方案替代的成本就高了。比如某个新组件在低版本不支持,你只能用 view 和事件自己拼一个类似的交互。这种方案要慎重,因为自绘的交互和原生组件在手感、无障碍、平台一致性上都有差距,而且维护成本高。我的原则是:自绘方案只在核心流程上做,非核心流程直接降级为提示。
给用户提示也有讲究。不要甩一句"请升级微信",用户根本不知道去哪升。可以写成"当前微信版本较低,该功能暂时无法使用,建议在微信设置中检查更新"。同时提供一个"我知道了"的关闭按钮,避免用户卡在这一步无法继续。
还有一类降级是静默降级,用户感知不到。比如某个动画效果在新版本上有,老版本上直接不显示动画,功能本身照常。这种最舒服,但要确保功能完整性不受影响。
这里顺带说一个和登录相关的兼容点。很多项目的登录流程是:调登录接口拿 code,再用 code 去服务端换取身份凭证。这个流程本身不依赖高版本基础库,但登录接口返回的内容在不同版本上可能有差异,服务端要能兼容。另外登录态过期后的重新登录逻辑,也要考虑低版本上接口行为一致性问题。
4.3 组件与渲染层的兼容坑
渲染层的问题最磨人,因为它往往不报错,只是表现异常。我挑几个高频的说。
第一是滚动。scroll-view 在 iOS 上的滚动体验和安卓不同,尤其是内部嵌套自定义组件、或者同时存在纵向和横向滚动时。常见的做法是给 scroll-view 加上增强滚动相关的属性,并在需要的时候用固定的高度或者 flex 布局约束它的尺寸。没有明确高度或者父级高度是 auto 的 scroll-view,在很多机型上滚不动。
第二是顶部导航栏高度。不同机型的胶囊按钮位置不一样,导航栏高度不能写死。标准做法是用获取胶囊位置信息的接口拿到按钮的位置和尺寸,再结合状态栏高度算出导航栏实际高度。这个接口本身有版本要求,低版本上不存在,所以要有兜底值。我在项目里一般把计算结果缓存到全局,避免每个页面重复计算。
第三是弹层类组件和滚动容器的冲突,也就是前面提到的日期选择器问题。解决思路是让弹层脱离滚动容器,或者用更高层级的方式渲染。具体用哪种,取决于你用的是原生组件还是自定义组件。
第四是滚动穿透。弹层打开后,底下的页面还能跟着滚。这在低版本基础库上更明显。常规做法是弹层出现时给底层页面加一个固定定位,或者监听触摸事件阻止默认行为,同时锁定页面滚动位置,关闭弹层后再恢复。
这些问题单独看都不难,难的是它们经常同时出现,而且还和基础库版本交织在一起。我的建议是建一个自己的兼容问题记录表,每次踩坑就记一条,包括触发条件、涉及版本、解决方案。累积到几十条之后,你会发现新项目的兼容工作快了一大截。
5. 常见问题与排查技巧实录
前面讲的都是"应该怎么做",这一节讲"实际会怎么错"。我把这些年遇到的典型问题整理成一张速查表,再补充几条文档里不会写的经验。
5.1 高频报错速查表
| 现象 | 常见原因 | 排查方向 |
|---|---|---|
| 某个函数 is not a function | 该 API 在低版本基础库不存在 | 查 API 起始版本,加 canIUse 判断 |
| 页面白屏,控制台无明显报错 | 渲染层能力不支持或组件注册失败 | 检查自定义组件配置、切换基础库版本复现 |
| iOS 能滚,安卓滚不动 | scroll-view 缺少明确高度或增强属性 | 给容器设固定高度,开启增强滚动 |
| 日期选择器在部分 iOS 点击无反应 | 弹层被滚动容器拦截事件 | 移出滚动容器或改用原生组件 |
| 底部弹层出现后页面跟着滚 | 滚动穿透 | 弹层打开时锁定页面滚动并恢复位置 |
| 顶部导航栏错位 | 导航栏高度写死 | 用胶囊位置接口动态计算,加兜底值 |
| 真机与模拟器表现不同 | 模拟器基础库与真机微信版本不一致 | 以真机为准,在目标机型复现 |
| 升级后老功能失效 | 用了新版才有的组件属性 | 属性做存在性判断,缺失时走默认逻辑 |
这张表里的每一行我基本都实际遇到过。用法很简单:出问题时先定位到现象所在行,按排查方向走一遍,大部分情况能快速收敛。
排查过程中有个通用技巧:先用最小复现。把出问题的页面临时改成一个只有核心组件的最小页面,切换基础库版本测试。如果最小页面能复现,问题就在组件或版本层面;如果复现不了,问题在业务逻辑和页面结构的耦合上。这一步能省掉大量猜测时间。
还有一个技巧是对比版本日志。微信官方每个基础库版本都有更新说明,遇到某个版本才开始出现的问题,去翻对应版本的日志,经常能直接找到原因。这个习惯我强烈建议养成,比在论坛里搜半天有效得多。
5.2 几条不成文的经验
第一,不要在小程序里处理"用户主动降级微信"这种情况。理论上存在,但概率极低,为它写兼容代码不划算。把精力放在主流版本区间的兼容上。
第二,版本判断尽量集中管理。别在几十个页面里各写一套判断逻辑,统一封一个工具模块,需要改的时候改一处。我见过一个项目,版本判断散落在各个文件里,后来调整最低版本时漏改了好几处,导致线上出现不一致的行为。
第三,上线前做一次"最低版本全量走查"。把开发者工具的基础库切到后台设置的最低版本,把核心流程完整走一遍。这个动作花不了半小时,但能拦掉大部分版本相关的线上问题。很多团队的新功能都只在最新版本上测过,一上线就翻车。
第四,灰度和版本要一起考虑。新功能发布时,如果依赖新版本基础库,先在小范围用户里验证,确认低版本用户没有异常后再全量。不要只看新功能的成功率,还要看整体进入率有没有掉。
第五,保留一份历史版本的问题记录。有些问题在特定版本上反复出现,比如某个版本的某个组件在特定机型上有渲染缺陷。记录下版本号和现象,下次遇到同样问题能直接对上号,不用重新查。
第六,关于胶囊按钮和右上角菜单这类客户端层面的元素,开发者能做的很有限。要清楚哪些是平台固定的、不能动的,别在这上面花时间研究"怎么去掉",把精力放在可控的范围内。
6. 一次版本升级的完整复盘
讲完方法,我拿一个自己做过的真实项目把整条链路串一遍,这样比零散的知识点更好记。项目是一个电商类的工具小程序,用户里有相当一部分是安卓中低端机,上线半年后想升级到新版基础库以使用新的渲染优化能力。
第一步是看数据。后台版本分布显示,低于目标版本的用户占 6%,其中大部分是安卓 8 以下机型。这个比例比预期高,所以我们决定先不急着提最低版本,而是先写兼容、后提版本。
第二步是定最低版本。我们没有一步提到目标版本,而是先定了一个中间值,把低于它的用户比例压到 2% 以内,观察两周进入率。这一步很关键,一次提太多容易被投诉打回来。
第三步是改代码。把项目里所有有版本门槛的 API 和组件属性列了一遍,一共二十多处,逐个加 canIUse 判断和降级分支。其中三处是核心流程,做了自绘替代;其余的非核心功能直接降级为提示。这一步花了大约一周,主要时间在回归测试上。
第四步是走查。用开发者工具的版本切换功能,把最低版本和最新版本各走一遍核心流程,重点是登录、下单、支付这三个链路。真机上找了两台老安卓机单独验证,发现一处滚动问题,调整了容器高度后解决。
第五步是上线和观察。先小范围灰度,重点看进入率和报错率。两天后数据稳定,再全量。全量后又观察了一周,没有明显异常,才在后台提交了最低版本设置。
整个过程下来,最大的体会是:版本升级不是一个技术动作,而是一个运营节奏。你既要技术上准备好,也要给用户留出升级和适应的时间。急着一步到位,往往适得其反。另外我个人的经验是,把版本相关的改动和业务功能改动分开上线,这样出问题时能快速定位是哪个改动引起的。混在一起发,排查成本会成倍上升。
最后分享一个小技巧:在建项目初期就在 README 里维护一份"基础库版本清单",记录项目当前的最低版本、用到的有版本门槛的 API、以及每个的降级策略。这东西平时看着没用,等团队换人或者一年后回来看代码时,能救命。基础库这件事,前期多花半小时,后期少熬几个通宵。