- 有赞前端质量保障体系
前言 最近一年多一直在做前端的一些测试,从小程序到店铺装修,基本都是纯前端的工作,刚开始从后端测试转为前端测试的时候,对前端东西茫然无感,而且团队内没有人做过纯前端的测试工作,只能一边踩坑一边总结经验,然后将容易出现问题的点形成体系、不断总结摸索,最终形成了目前的一套前端测试解决方案。在此,将有赞的前端质量保障体系进行总结,希望和大家一起交流。 先来全局看下有赞前端的技术架构和针对每个不同的层次,主要做了哪些保障质量的事情: [图片] [图片] 有赞的 Node 技术架构分为业务层、基础框架层、通用组件和基础服务层,我们日常比较关注的是基础框架、通用组件和业务层代码。Node 业务层做了两件事情,一是提供页面渲染的 client 层,用于和 C 端用户交互,包括样式、行为 js 等;二是提供数据服务的 server 层,用于组装后台提供的各种接口,完成面向 C 端的接口封装。 对于每个不同的层,我们都做了一些事情来保障质量,包括: 针对整个业务层的 UI 自动化、核心接口|页面拨测; 针对 client 层的 sentry 报警; 针对 server 层的接口测试、业务报警; 针对基础框架和通用组件的单元测试; 针对通用组件变更的版本变更报警; 针对线上发布的流程规范、用例维护等。 下面就来分别讲一下这几个维度的质量保障工作。 一、UI 自动化 很多人会认为,UI 自动化维护成本高、性价比低,但是为什么在有赞的前端质量保证体系中放在了最前面呢? 前端重用户交互,单纯的接口测试、单元测试不能真实反映用户的操作路径,并且从以往的经验中总结得出,因为各种不可控因素导致的发布 A 功能而 B 功能无法使用,特别是核心简单场景的不可用时有出现,所以每次发布一个应用前,都会将此应用提供的核心功能执行一遍,那随着业务的不断积累,需要回归的测试场景也越来越多,导致回归的工作量巨大。为了降低人力成本,我们亟需通过自动化手段释放劳动力,所以将核心流程回归的 UI 自动化提到了最核心地位。 当然,UI 自动化的最大痛点确实是维护成本,为降低维护成本,我们将页面分为组件维度、页面维度,并提供统一的包来处理公用组件、特殊页面的通用逻辑,封装通用方法等,例如初始化浏览器信息、环境选择、登录、多网点切换、点击、输入、获取元素内容等等,业务回归用例只需要关注自己的用例操作步骤即可。 1、框架选择 – puppeteer[1],它是由 Chrome 维护的 Node 库,基于 DevTools 协议来驱动 chrome 或者 chromium 浏览器运行,支持 headless 和 non-headless 两种方式。官网提供了非常丰富的文档,简单易学。 UI 自动化框架有很多种,包括 selenium、phantom;对比后发现 puppeteer 比较轻量,只需要增加一个 npm 包即可使用;它是基于事件驱动的方式,比 selenium 的等待轮询更稳当、性能更佳;另外,它是 chrome 原生支持,能提供所有 chrome 支持的 api,同时我们的业务场景只需要覆盖 chrome,所以它是最好的选择。 – mocha[2] + mochawesome[3],mocha 是比较主流的测试框架,支持 beforeEach、before、afterEach、after 等钩子函数,assert 断言,测试套件,用例编排等。 mochawesome 是 mocha 测试框架的第三方插件,支持生成漂亮的 html/css 报告。 js 测试框架同样有很多可以选择,mocha、ava、Jtest 等等,选择 mocha 是因为它更灵活,很多配置可以结合第三方库,比如 report 就是结合了 mochawesome 来生成好看的 html 报告;断言可以用 powser-assert 替代。 2、脚本编写 封装基础库 封装 pc 端、h5 端浏览器的初始化过程 封装 pc 端、h5 端登录统一处理 封装页面模型和组件模型 封装上传组件、日期组件、select 组件等的统一操作方法 封装 input、click、hover、tap、scrollTo、hover、isElementShow、isElementExist、getElementVariable 等方法 提供根据 “html 标签>>页面文字” 形式获取页面元素及操作方法的统一支持 封装 baseTest,增加用例开始、结束后的统一操作 封装 assert,增加断言日志记录 业务用例 安装基础库 编排业务用例 3、执行逻辑 分环境执行 增加预上线环境代码变更触发、线上环境自动执行 监控源码变更 增加 gitlab webhook,监控开发源码合并 master 时自动在预上线环境执行 增加 gitlab webhook,监控测试用例变更时自动在生产环境执行 每日定时执行 增加 crontab,每日定时执行线上环境 [图片] [图片] [图片] [图片] 二、接口测试 接口测试主要针对于 Node 的 server 层,根据我们的开发规范,Node 不做复杂的业务逻辑,但是需要将服务化应用提供 dubbo 接口进行一次转换,或将多个 dubbo 接口组合起来,提供一个可供 h5/小程序渲染数据的 http 接口,转化过程就带来了各种数据的获取、组合、转换,形成了新的端到端接口。这个时候单单靠服务化接口的自动化已经不能保障对上层接口的全覆盖,所以我们针对 Node 接口也进行自动化测试。为了使用测试内部统一的测试框架,我们通过 java 去请求 Node 提供的 http 接口,那么当用例都写好之后,该如何评判接口测试的质量?是否完全覆盖了全部业务逻辑呢?此时就需要一个行之有效的方法来获取到测试的覆盖情况,以检查有哪些场景是接口测试中未覆盖的,做到更好的查漏补缺。 – istanbul[4] 是业界比较易用的 js 覆盖率工具,它利用模块加载的钩子计算语句、行、方法和分支覆盖率,以便在执行测试用例时透明的增加覆盖率。它支持所有类型的 js 覆盖率,包括单元测试、服务端功能测试以及浏览器测试。 但是,我们的接口用例写在 Java 代码中,通过 Http 请求的方式到达 Node 服务器,非 js 单测,也非浏览器功能测试,如何才能获取到 Node 接口的覆盖率呢? 解决办法是增加 cover 参数:–handle-sigint,通过增加 --handle-sigint 参数启动服务,当服务接收到一个 SIGINT 信号(linux 中 SIGINT 关联了 Ctrl+C),会通知 istanbul 生成覆盖率。这个命令非常适合我们,并且因此形成了我们接口覆盖率的一个模型: [代码]1. istanbule --handle-sigint 启动服务 2. 执行测试用例 3. 发送 SIGINT结束istanbule,得到覆盖率 [代码] 最终,解决了我们的 Node 接口覆盖率问题,并通过 jenkins 持续集成来自动构建 [图片] [图片] [图片] 当然,在获取覆盖率的时候有需求文件是不需要统计的,可以通过在根路径下增加 .istanbule.yml 文件的方式,来排除或者指定需要统计覆盖率的文件 [代码]verbose: false instrumentation: root: . extensions: - .js default-excludes: true excludes:['**/common/**','**/app/constants/**','**/lib/**'] embed-source: false variable: __coverage__ compact: true preserve-comments: false complete-copy: false save-baseline: false baseline-file: ./coverage/coverage-baseline.json include-all-sources: false include-pid: false es-modules: false reporting: print: summary reports: - lcov dir: ./coverage watermarks: statements: [50, 80] lines: [50, 80] functions: [50, 80] branches: [50, 80] report-config: clover: {file: clover.xml} cobertura: {file: cobertura-coverage.xml} json: {file: coverage-final.json} json-summary: {file: coverage-summary.json} lcovonly: {file: lcov.info} teamcity: {file: null, blockName: Code Coverage Summary} text: {file: null, maxCols: 0} text-lcov: {file: lcov.info} text-summary: {file: null} hooks: hook-run-in-context: false post-require-hook: null handle-sigint: false check: global: statements: 0 lines: 0 branches: 0 functions: 0 excludes: [] each: statements: 0 lines: 0 branches: 0 functions: 0 excludes: [] [代码] 三、单元测试 单元测试在测试分层中处于金字塔最底层的位置,单元测试做的比较到位的情况下,能过滤掉大部分的问题,并且提早发现 bug,也可以降低 bug 成本。推行一段时间的单测后发现,在有赞的 Node 框架中,业务层的 server 端只做接口组装,client 端面向浏览器,都不太适合做单元测试,所以我们只针对基础框架和通用组件进行单测,保障基础服务可以通过单测排除大部分的问题。比如基础框架中店铺通用信息服务,单测检查店铺信息获取;比如页面级商品组件,单测检查商品组件渲染的 html 是否和原来一致。 单测方案试行了两个框架: Jest[5] ava[6] 比较推荐的是 Jest 方案,它支持 Matchers 方式断言;支持 Snapshot Testing,可测试组件类代码渲染的 html 是否正确;支持多种 mock,包括 mock 方法实现、mock 定时器、mock 依赖的 module 等;支持 istanbule,可以方便的获取覆盖率。 总之,前端的单测方案也越来越成熟,需要前端开发人员更加关注 js 单测,将 bug 扼杀在摇篮中。 四、基础库变更报警 上面我们已经对基础服务和基础组件进行了单元测试,但是单测也不能完全保证基础库的变更完全没有问题,伴随着业务层引入新版本的基础库,bug 会进一步带入到业务层,最终影响 C 端用户的正常使用。那如何保障每次业务层引入新版本的基础库之后能做到全面的回归?如何让业务测试同学对基础库变更更加敏感呢?针对这种情况,我们着手做了一个基础库版本变更的小工具。实现思路如下: [代码]1. 对比一次 master 代码的提交或 merge 请求,判断 package.json 中是否有特定基础库版本变更 2. 将对应基础库的前后两个版本的代码对比发送到测试负责人 3. 根据 changelog 判断此次回归的用例范围 4. 增加 gitlab webhook,只有合并到合并发布分支或者 master 分支的代码才触发检查 [代码] 这个小工具的引入能及时通知测试人员针对什么需求改动了基础组件,以及这次基础组件的升级主要影响了哪些方面,这样能避免相对黑盒的测试。 第一版实现了最简功能,后续再深挖需求,可以做到前端代码变更的精准测试。 [图片] 五、sentry 报警 在刚接触前端测试的时候,js 的报错没有任何追踪,对于排查问题和定位问题有很大困扰。因此我们着手引入了 sentry 报警监控,用于监控线上环境 js 的运行情况。 – sentry[7] 是一款开源的错误追踪工具,它可以帮助开发者实时监控和修复崩溃。 开始我们接入的方式比较简单粗暴,直接全局接入,带来的问题是报警信息非常庞大,全局上报后 info、warn 信息都会打出来。 更改后,使用 sentry 的姿势是: sentry 的全局信息上报,并进行筛选 错误类型: TypeError 或者 ReferenceError 错误出现用户 > 1k 错误出现在 js 文件中 出现错误的店铺 > 2家 增加核心业务异常流程的主动上报 最终将筛选后的错误信息通过邮件的形式发送给告警接收人,在固定的时间集中修复。 [图片] [图片] 六、业务报警 除了 sentry 监控报警,Node 接口层的业务报警同样是必不可少的一部分,它能及时发现 Node 提供的接口中存在的业务异常。这部分是开发和运维同学做的,包括在 Node 框架底层接入日志系统;在业务层正确的上报错误级别、错误内容、错误堆栈信息;在日志系统增加合理的告警策略,超过阈值之后短信、电话告警,以便于及时发现问题、排查问题。 业务告警是最能快速反应生产环境问题的一环,如果某次发布之后发生告警,我们第一时间选择回滚,以保证线上的稳定性。 七、约定规范 除了上述的一些测试和告警手段之外,我们也做了一些流程规范、用例维护等基础建设,包括: 发布规范 多个日常分支合并发布 限制发布时间 规范发布流程 整理自测核心检查要点 基线用例库 不同业务 P0 核心用例定期更新 项目用例定期更新到业务回归用例库 线上问题场景及时更新到回归用例库 目前有赞的前端测试套路基本就是这样,当然有些平时的努力没有完全展开,例如接口测试中增加返回值结构体对比;增加线上接口或页面的拨测[8];给开发进行自测用例设计培训等等。也还有很多新功能探索中,如接入流量对比引擎,将线上流量导到预上线环境,在代码上线前进行对比测试;增加UI自动化的截图对比;探索小程序的UI自动化等等。 参考链接 [1] https://github.com/GoogleChrome/puppeteer [2] https://www.npmjs.com/package/mocha [3] https://www.npmjs.com/package/mochawesome [4] https://github.com/gotwarlost/istanbul [5] https://github.com/facebook/jest [6] https://github.com/avajs/ava [7] https://docs.sentry.io [8] https://tech.youzan.com/youzan-online-active-testing/
2019-04-25 - 小程序自定义组件知多少
自定义组件 why 代码的复用 在起初小程序只支持 Page 的时候,就会有这样蛋疼的问题:多个页面有相同的组件,每个页面都要复制粘贴一遍,每次改动都要全局搜索一遍,还说不准哪里改漏了就出翔了。 组件化设计 在前端项目中,组件化是很常见的方式,某块通用能力的抽象和设计,是一个必备的技能。组件的管理、数据的管理、应用状态的管理,这些在我们设计的过程中都是需要去思考的。当然你也可以说我就堆代码就好了,不过一个真正的码农是不允许自己这么随便的! 所以,组件化是现代前端必须掌握的生存技能! 自定义组件的实现 一切都从 Virtual DOM 说起 前面《解剖小程序的 setData》有讲过,基于小程序的双线程设计,视图层(Webview 线程)和逻辑层(JS 线程)之间通信(表现为 setData),是基于虚拟 DOM 来实现数据通信和模版更新的。 自定义组件一样的双线程,所以一样滴基于 Virtual DOM 来实现通信。那在这里,Virtual DOM 的一些基本知识(包括生成 VD 对象、Diff 更新等),就不过多介绍啦~ Shadow DOM 模型 基于 Virtual DOM,我们知道在这样的设计里,需要一个框架来支撑维护整个页面的节点树相关信息,包括节点的属性、事件绑定等。在小程序里,Exparser 承担了这个角色。 前面《关于小程序的基础库》也讲过,Exparser 的主要特点包括: 基于 Shadow DOM 模型 可在纯 JS 环境中运行 Shadow DOM 是什么呢,它就是我们在写代码时候写的自定义组件、内置组件、原生组件等。Shadow DOM 为 Web 组件中的 DOM 和 CSS 提供了封装。Shadow DOM 使得这些东西与主文档的 DOM 保持分离。 简而言之,Shadow DOM 是一个 HTML 的新规范,其允许开发者封装 HTML 组件(类似 vue 组件,将 html,css,js 独立部分提取)。 例如我们定义了一个自定义组件叫[代码]<my-component>[代码],你在开发者工具可以见到: [图片] [代码]#shadow-root[代码]称为影子根,DOM 子树的根节点,和文档的主要 DOM 树分开渲染。可以看到它在[代码]<my-component>[代码]里面,换句话说,[代码]#shadow-root[代码]寄生在[代码]<my-component>[代码]上。[代码]#shadow-root[代码]可以嵌套,形成节点树,即称为影子树(Shadow Tree)。 像这样: [图片] Shadow Tree 拼接 既然组件是基于 Shadow DOM,那组件的嵌套关系,其实也就是 Shadow DOM 的嵌套,也可称为 Shadow Tree 的拼接。 Shadow Tree 拼接是怎么做的呢?一切又得从模版引擎讲起。 我们知道,Virtual DOM 机制会将节点解析成一个对象,那这个对象要怎么生成真正的 DOM 节点呢?数据变更又是怎么更新到界面的呢?这大概就是模版引擎做的事情了。 《前端模板引擎》里有详细描述模版引擎的机制,通常来说主要有这些: DOM 节点的创建和管理:[代码]appendChild[代码]/[代码]insertBefore[代码]/[代码]removeChild[代码]/[代码]replaceChild[代码]等 DOM 节点的关系(嵌套的处理):[代码]parentNode[代码]/[代码]childNodes[代码] 通常创建后的 DOM 节点会保存一个映射,在更新的时候取到映射,然后进行处理(通常包括替换节点、改变内容[代码]innerHTML[代码]、移动删除新增节点、修改节点属性[代码]setAttribute[代码]) 在上面的图我们也可以看到,在 Shadow Tree 拼接的过程中,有些节点并不会最终生成 DOM 节点,例如[代码]<slot>[代码]这种。 但是,常用的前端模版引擎,能直接用在小程序里吗? 双线程的难题 自定义组件渲染流程 双线程的设计,给小程序带来了很多便利,安全性管控力都拥有了,当然什么鬼东西都可以比作一把双刃剑,双线程也不例外。 我们知道,小程序分为 Webview 和 JS 双线程,逻辑层里是没法拿到真正的 DOM 节点,也没法随便动态变更页面的。那在这种情况下,我们要怎么去使用映射来更新模版呢(因为我们压根拿不到 Webview 节点的映射)? 所以在双线程下,其实两个线程都需要保存一份节点信息。这份节点信息怎么来的呢?其实就是我们需要在创建组件的时候,通过事件通知的方式,分别在逻辑层和视图层创建一份节点信息。 同时,视图层里的组件是有层级关系的,但是 JS 里没有怎么办?为了维护好父子嵌套等节点关系,所以我们在 逻辑层也需要维护一棵 Shadow Tree。 那么我们自定义组件的渲染流程大概是: 组件创建。 逻辑层:先是 wxml + js 生成一个 JS 对象(因为需要访问组件实例 this 呀),然后是 JS 其中节点部分生成 Virtual DOM,拼接 Shadow Tree 什么的,最后通过底层通信通知到 视图层 视图层:拿到节点信息,然后吭哧吭哧开始创建 Shadow DOM,拼接 Shadow Tree 什么的,最后生成真实 DOM,并保留下映射关系 组件更新。 这时候我们知道,不管是逻辑层,还是视图层,都维护了一份 Shadow Tree,要怎么保证他们之间保持一致呢? 让 JS 和 Webview 的组件保持一致 为了让两边的 Shadow Tree 保持一致,可以使用同步队列来传递信息。(这样就不会漏掉啦) 同步队列可以,每次变动我们就往队列里塞东西就好了。不过这样还会有个问题,我们也知道 setData 其实在实际项目里是使用比较频繁的,要是像 Component 的 observer 里做了 setData 这类型的操作,那不是每次变动会导致一大堆的 setDate?这样通信效率会很低吧? 所以,其实可以把一次操作里的所有 setData 都整到一次通信里,通过排序保证好顺序就好啦。 Page 和 Component Component 是 Page 的超集 事实上,小程序的页面也可以视为自定义组件。因而,页面也可以使用[代码]Component[代码]构造器构造,拥有与普通组件一样的定义段与实例方法。但此时要求对应 json 文件中包含[代码]usingComponents[代码]定义段。 来自官方文档-Component 所以,基于 Component 是 Page 的超集,那么其实组件的渲染流程、方式,其实跟页面没多大区别,应该可以一个方式去理解就差不多啦。 页面渲染 既然页面就是组件,那其实页面的渲染流程跟组件的渲染流程基本保持一致。 视图层渲染,可以参考7.4 视图层渲染说明。 结束语 其实很多新框架新工具出来的时候,经常会让人眼前一亮,觉得哇好厉害,哇好高大上。 但其实更多时候,我们需要挖掘新事物的核心,其实大多数都是在原有的事物上增加了个新视角,从不一样的视角看,看到的就不一样了呢。作为一名码农,我们要看到不变的共性,变化的趋势。
2019-04-01 - 关于小程序的基础库
小程序基础库的组成 基础库成分 关于基础库的成分,不得不提到我们之前说过的小程序渲染机制,参考 React 的 Virtual DOM。 [图片] 基础库除了处理 VD 的渲染问题,它还包括内置组件和逻辑层API,总的来说负责处理数据绑定、组件系统、事件系统、通信系统等一系列框架逻辑。 小程序的基础库是 JavaScript 编写的,它可以被注入到渲染层和逻辑层运行。在渲染层可以用各类组件组建界面的元素,在逻辑层可以用各类 API 来处理各种逻辑。 同时,小程序的一些补充能力:自定义组件和插件,也有相应的基础代码,当然也需要添加到基础库里。 所以我们可以看到,小程序的基础库主要包括: 提供 VD 渲染机制相关基础代码。(Exparser 框架) 提供封装后的内置组件。 提供逻辑层的 API。 提供其他补充能力(自定义组件和插件等)的基础代码。 [图片] Exparser 框架 Exparser 是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各种组件提供基础的支持。 小程序内的所有组件,包括内置组件和自定义组件,都由 Exparser 组织管理。 Exparser 会维护整个页面的节点树相关信息,包括节点的属性、事件绑定等,相当于一个简化版的 Shadow DOM 实现。Exparser 的主要特点包括以下几点: 基于 Shadow DOM 模型:模型上与 WebComponents 的 ShadowDOM 高度相似,但不依赖浏览器的原生支持,也没有其他依赖库;实现时,还针对性地增加了其他 API 以支持小程序组件编程。 可在纯 JS 环境中运行:这意味着逻辑层也具有一定的组件树组织能力。 高效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺寸也较小。 基于这个框架,内置了一套组件,以涵盖小程序的基础功能,便于开发者快速搭建出任何界面。同时也提供了自定义组件的能力,开发者可以自行扩展更多的组件,以实现代码复用。 内置组件 小程序基于 Exparser 框架,内置了一套组件,提供了视图容器类、表单类、导航类、媒体类、开放类等几十种组件。 内置组件在小程序框架里的定义是:在小程序架构里无法实现或者实现不好某类功能,使用组件内置到小程序框架里。 常见包括: 开放类组件:如 open-data 组件提供展示群名称、用户信息等微信体系下的隐私信息,有 button 组件里 open-type 属性所提供分享、跳转 App 等敏感操作的能力 视图容器类组件:如 movable-view 这种因双线程模型导致手势识别不好实现的组件(在双线程模型中,触摸事件从渲染层发出,派发到逻辑层,这中间是有一定的延时而导致视图跟随手指运动这类交互变得有些卡顿) API 宿主环境提供了丰富的API,可以很方便调起微信提供的能力。 小程序提供的 API 按照功能主要分为几大类:网络、媒体、文件、数据缓存、位置、设备、界面、界面节点信息还有一些特殊的开放接口。 需要注意 API 调用大多都是异步的。 自定义组件 自定义组件是开发者可以自行扩充的组件。开发者可以将常用的节点树结构提取成自定义组件,实现代码复用。 在使用自定义组件的小程序页面中,Exparser 将接管所有的自定义组件注册与实例化。以 Component 为例: 在小程序启动时,构造器会将开发者设置的 properties、data、methods 等定义段,写入 Exparser 的组件注册表中。 这个组件在被其它组件引用时,就可以根据这些注册信息来创建自定义组件的实例。 Page 构造器的大体运行流程与之相仿,只是参数形式不一样。这样每个页面就有一个与之对应的组件,称为“页面根组件”。 在初始化页面时,Exparser 会创建出页面根组件的一个实例,用到的其他组件也会响应创建组件实例(这是一个递归的过程)。 插件 插件是对一组 js 接口、自定义组件或页面的封装,用于嵌入到小程序中使用。 插件不能独立运行,必须嵌入在其他小程序中才能被用户使用;而第三方小程序在使用插件时,也无法看到插件的代码。因此,插件适合用来封装自己的功能或服务,提供给第三方小程序进行展示和使用。 插件开发者可以像开发小程序一样编写一个插件并上传代码,在插件发布之后,其他小程序方可调用。小程序平台会托管插件代码,其他小程序调用时,上传的插件代码会随小程序一起下载运行。 小程序基础库机制 基础库的载入 在开发网页时,经常会引用很多开源的 JS 库,在使用到这些库所提供的 API 前,我们需要先在业务代码前边引入这些库。 同样道理,我们需要在启动 APP 之前载入基础库,接着再载入业务代码。由于小程序的渲染层和逻辑层是两个线程管理,而我们 一般说起基础库,也通常包括 WebView 基础库(渲染层),和 AppService 基础库(逻辑层)。 显然,所有小程序在微信客户端打开的时候,都需要注入相同的基础库。所以,小程序的基础库不会被打包在某个小程序的代码包里边,它会被提前内置在微信客户端。 将基础库内置在微信客户端,有两个好处: 降低业务小程序的代码包大小。 可以单独修复基础库中的Bug,无需修改到业务小程序的代码包。 小程序的启动 在小程序启动前,微信会提前准备好一个页面层级用于展示小程序的首页。 这里就包括了逻辑层和渲染层分别的初始化以及公共库的注入。 [图片] 在小程序启动时,微信会为小程序展示一个固定的启动界面,界面内包含小程序的图标、名称和加载提示图标。此时,微信会在背后完成几项工作:下载小程序代码包、加载小程序代码包、初始化小程序首页。 [图片] 基础库的更新 小程序的很多能力需要微信客户端来支撑,例如蓝牙、直播能力、微信运动等,可以说,小程序基础库的迭代离不开微信客户端的发布。 为了避免新版本的基础库给线上小程序带来未知的影响,微信客户端都是携带上一个稳定版的基础库发布的。等到微信客户端正式发布后,小程序会开始灰度推送新版本的基础库到微信客户端里,在这个过程需要仔细监控各类异常现象以及开发者和用户的反馈,一般灰度时长为12小时,灰度结束后,用户设备上就会有新版本的基础库。如果存在重大Bug,那此次推送会被回退。 参考 《小程序开发指南——小程序基础库的更新迭代》 《小程序开发指南——6.2 组件系统》 结束语 本节大致结合了小程序的启动来讲了下小程序的基础库。其实很多都能在小程序开发指南里找到,只是文字非常详(fan)细(duo),看一遍未必能记住,但是第二遍又找不到了。 哈哈哈吐槽下小程序的文档,很详细就是有点容易找不到。
2019-02-27