《小程序开发实践与优化》
来自于2020年7月23日平安智慧城市\智慧生活事业部\交付前端组本人的技术分享
小程序设计之初
一般来说,渲染界面的技术有三种:
- 用纯客户端原生技术来渲染
- 用纯 Web 技术来渲染
- Hybrid 技术
Hybrid 技术
- 基于 WebView UI 的基础方案,市面上大部分主流 App 都有采用,例如微信JS-SDK,通过 JSBridge 完成 H5 与 Native 的双向通讯,从而赋予H5一定程度的原生能力。
- 基于 Native UI 的方案,例如 React-Native、Weex。在赋予 H5 原生API能力的基础上,进一步通过 JSBridge 将js解析成的虚拟节点树(Virtual DOM)传递到 Native 并使用原生渲染。
- 小程序方案,也是通过更加定制化的 JSBridge,并使用双 WebView 双线程的模式隔离了UI渲染与JS逻辑,形成了特殊的开发模式,加强了 H5 与 Native 混合程度,提高了页面性能及开发体验。
以上的三种方案,其实同样都是基于 JSBridge 完成的通讯层,第2 、3种方案,其实可以看做是在方案一的基础上,继续通过不同的新技术进一步提高了应用的混合程度。因此,JSBridge 也是整个混合应用最关键的部分,例如我们在设置微信分享时用到的 JS-SDK,wx对象 便是我们最常见的 JSBridge:
这个方案就是我们所说的 JSBridge,而实现的关键,便是作为容器的 WebView,一切的原理都是基于 WebView 的机制。
微信分享时用到的 JS-SDK,wx对象 便是我们最常见的 JSBridge:
小程序的架构
- WXML 和 WXSS 工作在渲染层(webview)
- JS脚本工作在逻辑层(jsCore)
- 并且每个小程序页面都是对应一个 webview 线程,这样性能比较好
相较于后端,前端的性能优化会更直接与用户的体验挂钩。从用户体验侧来说,前端服务 5s 的加载时间优化缩减 80%(1s) 与后端服务 50ms 的响应优化缩减 80%(10ms) 相比,用户的体验提升会更大。因此很多时候,与体验相关的性能的瓶颈会出现在前端。
微信小程序的框架包含两部分View视图层、App Service逻辑层,View层用来渲染页面结构,AppService层用来逻辑处理、数据请求、接口调用,它们在两个线程里运行。
视图层使用WebView渲染,逻辑层使用JSCore运行。 视图层和逻辑层通过系统层的JSBridage进行通信,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理。
小程序与普通网页开发的区别?
小程序的主要开发语言是 JavaScript ,所以通常小程序的开发会被用来同普通的网页开发来做对比。两者有很大的相似性,对于前端开发者而言,从网页开发迁移到小程序的开发成本并不高,但是二者还是有些许区别的。
网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。网页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作。而如上文所述,小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
网页开发者需要面对的环境是各式各样的浏览器,PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对Safari、Chrome以及 iOS、Android 系统中的各式 WebView 。而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具,小程序中三大运行环境也是有所区别的。
小程序运行环境:
运行环境:
- 在ios中,小程序的JavaScript代码是运行在JavaScriptCore中,是由WKWebView来渲染的
- 在Android中,小程序的JavaScript代码是通过X5 JSCore来解析,是由腾讯X5内核来渲染的
- 在开发工具中,小程序的JavaScript代码运行在NWJS中,是ChromeWebView来渲染的
特点:
- 微信小程序中不是使用传统的html标签来开发,而是使用WXML标记语言
- 没有window全局变量,但提供了内置的wx.全局方法集
- 安卓版本可以将小程序添加到手机桌面,类似于PWA应用
- 没有超链接,iframe只能在之内的WebView容器内使用
- 事件绑定和条件渲染全部都写在WXML中,这点类似VUE的语法结构
- 数据绑定采用Mustache双大括号语法
- 无法操作DOM,通过setData改变page data来操作数据驱动,这点和react的 setState很像
- 目前还无法直接分享到朋友圈,正在灰度测试
https://developers.weixin.qq.com/ebook?action=get_post_info&docid=000668c6910b784b00860870a5ac0a
小程序从用户点击到销毁经历怎样的过程是怎样的?
可以用以下的流程图来看:
1、点击打开
2、加载代码包
3、解析app.json渲染全局样式
4、加载文件,解析代码
5、创建View进程
6、通知AppSerice
7、显示触发onReady
8、关闭触发onUnload
而这一整次的数据渲染是怎样进行的?
也就是我们页面中的page data()在 setData 发生了什么?
渲染层 -> Native (点击事件)
Native -> 逻辑层 (点击事件)
逻辑层 -> Native (setData)
Native -> 渲染层 (setData)
可以看到通信一次是比较麻烦且耗时,虽然 setData 的设计和 React 类似,但是内部却是不同的,React 是异步在下一个时间节点合并 setState 然后进行 state 的处理,属于是异步。而 setData 的修改和 Vue 的机制类似,是对 data 进行同步的更新,但是对于渲染层的改变却是异步的。
我们发现小程序的组织结构和 Vue 很像,都是使用 template 语法,这样可以降低开发者使用门槛,
另一方面却使用类似 React 的 setState 的显示调用更新机制。
为什么不使用类似 Vue 一样的直接修改 data 的值呢?
因为小程序的软件架构,视图层是webview线程,逻辑层是jscore线程,并不具备直接通信的通道。
所以为了视图层和逻辑层的通信,两边都采用了 evaluateJavascript 来和 Native 层通信,导致了小程序必须得通过显示调用的方式来修改 data 的值,这样才能够通知到 Native 层。
evaluateJavascript 只能传字符串,
所以我们的 data 中的数据都会进行 JSON.stringify 转义成字符串进行传递。
代码包
分为 开发版、体验版、正式版 三种:
开发版:每个开发者在开发过程中点击“预览”生成的版本,每个小游戏可以有多个开发版,对于每个开发者本地只能有一个开发版;开发版代码包只能通过扫码获得;
体验版:通过在管理后台将特定开发版设置成体验版得到的版本,每个小游戏只能有一个体验版;
正式版:正式发布在线上的版本,每个小游戏只能有一个正式版
包大小限制:
代码包总大小不能超过 16M,单个分包不能超过 4M。
(最近正在灰度测试16M大包)
小程序的运行机制——前台/后台状态
- 小程序启动后,界面被展示给用户,此时小程序处于前台状态。
- 当用户点击右上角胶囊按钮关闭小程序,或者按了设备 Home 键离开微信时,小程序并没有完全终止运行,而是进入了后台状态,小程序还可以运行一小段时间。
- 当用户再次进入微信或再次打开小程序,小程序又会从后台进入前台。但如果用户很久没有再进入小程序,或者系统资源紧张,小程序可能被销毁,即完全终止运行。
小程序的运行机制——启动方式
冷启动:如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动。
热启动:如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动。
小程序的运行机制——更新机制
未启动时更新
开发者在管理后台发布新版本的小程序之后,如果某个用户本地有小程序的历史版本,此时打开的可能还是旧版本。微信客户端会有若干个时机去检查本地缓存的小程序有没有更新版本,如果有则会静默更新到新版本。总的来说,开发者在后台发布新版本之后,无法立刻影响到所有现网用户,但最差情况下,也在发布之后 24 小时之内下发新版本信息到用户。用户下次打开时会先更新最新版本再打开。
启动时更新
小程序每次冷启动时,都会检查是否有更新版本,如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。
如果需要马上应用最新版本,可以使用 wx.getUpdateManager API 进行处理。
小程序的运行机制——销毁时机
当小程序进入后台,可以维持一小段时间的运行状态,如果这段时间内都未进入前台,小程序会被销毁。
当小程序***占用系统资源过高***,可能会被系统销毁或被微信客户端主动回收。在 iOS 上,当微信客户端在一定时间间隔内连续收到系统内存告警时,会根据一定的策略,主动销毁小程序,并提示用户 「运行内存不足,请重新打开该小程序」。
小程序的登录及实名流程
登录的多种形式:
- 拉起微信授权登录
- 账号密码登录
- 手机号登录
- (登录不可以强制登录,不然不能通过微信审核)
实名流程三种方式:
- 银行卡实名
- 人脸实名
- 微信支付实名
小程序内嵌h5注意事项
- 在WebView容器内打开
<WebView src={this.state.targetUrl} />
WebView标签,作为h5的承载容器,条件需要同时满足 https、域名备案、根目录配置文件。- **潜在的问题: **可以用我们的nginx服务器转发链接到对方服务器,就不用配置服务器根目录文件,但是对方的接口可能和页面是不一样的,请求不对,需要转发所有的请求(文件、图片、接口),所以不建议这种方式
- 小程序跳转H5:
- 跳转时,先将url存到localstorage里面,再打开
<WebView src={this.state.targetUrl} />
webview页面时提取url并加载 - 潜在的问题:当对方的页面是用vue写的,H5的A页面跳到B页面,B页面进行返回操作不能用������.���ℎ,需要用router.push,需要用router.replace,push会造成返回时在h5页面无限循环跳
- 小程序跳转小程序:
- 使用限制
- 需要用户触发跳转
- 从 2.3.0 版本开始,若用户未点击小程序页面任意位置,则开发者将无法调用此接口自动跳转至其他小程序。
- 每个小程序可跳转的其他小程序数量限制为不超过 10 个
- 从 2.4.0 版本以及指定日期(具体待定)开始,开发者提交新版小程序代码时,如使用了跳转其他小程序功能,则需要在代码配置中声明将要跳转的小程序名单,限定不超过 10 个,否则将无法通过审核。
- H5跳转小程序:
- 可以调用
wx.miniProgram.navigateTo({ url: '/pages/login/login' })
- 前提是页面上要导入jssdk
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
开发框架选择:
选用taro或者uniapp这种编译工具,目前只编译微信和支付宝的话用taro就可以了,uniapp还可以编译为app,用taro开发,语言选用react做开发,门槛低,一套代码,分开编译,先编译微信,调整一些兼容代码之后再编译为支付宝小程序。
兼容调整的主要内容在与app.json配置文件中关于navigationBar相关设置,且该文件只支持静态配置,不支持动态变量渲染,所以只能在编译完之后手动改造
开发时的注意事项:
- 不能做强制登录,审核不过
- 内嵌的第三方业务H5需要是备案过的域名、https、并添加配置文件
- 人脸识别登录可以用南京统一身份认证的技术(一整套前后端),也可以用微信官方提供的技术,微信官方的技术需要额外的申请权限
- 静态资源尽量本地化,大图可以外链,首次加载时网速问题会导致页面残缺
- 页面内容(业务名称、链接、图标)可以做Json配置,这样做非常好,以后不需要微信审核,但是用户在网速不好的情况下,服务器瘫痪的情况下,页面一片白,风险较大
- 页面公告提示可配置话,在后台发版、压测试,用远程json的形式,实时动态开启页面Notice提示
- 尽量提前预定发布事件,微信审核在工作日较快,一般半天内可以审核玩,周末及工作日晚上审核较慢
- 小程序发布之后,可以在微信后台开启小程序测评,开启之后,根据小程序的测评功能,可以开启一系列功能,比如 2小时内极速审核、微信人脸身份认证接口、被搜索加权、16M大包体、实时日志
发布时的注意事项:
- 页面模块较多,工程量大的时候,可以采用小程序的分包开发形式
- 页面上的数据,尽量多采用本地Storage的形式,与用户的登录态绑定,退出即清空
- 页面上要做每次打开更新检测及提示,采用微信api那一套
- 页面除了做微信数据统计也可以做腾讯mta数据统计和百度统计,做事件分析,这样可以较准确的统计,用户的点击次数,或者实名情况
微信小程序的开发资源有哪些:——UI组件库
WeUI ,腾讯微信,原生基础样式,风格简约大方,可以与微信本身风格一致,升级版为KboneUI
iViewUI,TalkingData ,比较实用
MinUI ,由蘑菇街,与其他UI库相比,更加注重页面文本模块的细节布局
ColorUI ,文晓港团队,库如其名,组件库丰富,年轻化,花里胡哨的好看
Vant UI,有赞,为电商购物类小程序提供了很多现成的基础组件
TaroUI ,京东,整体风格简约、清新、统一,适合工具、读书、资讯、教育、商务等类型的小程序
WuxUI,skyvow (GitHub 账号名) ,组件库最为丰富,又很多其他库所没有的组件,如进度环、骨架屏、筛选栏、数字键盘、结果页等实用工具类组件
Demo和详情可见 https://www.ifanr.com/minapp/1196588
微信小程序的开发资源有哪些:——开发框架
微信小程序的开发资源有哪些:——开发资讯
每周为你提供高质量的关于小程序、h5等前端领域的文章和项目
https://www.ctolib.com/Tnfe-TNFE-Weekly.html
微信小程序开发资源汇总
https://www.ctolib.com/javascript/categories/javascript-wechat-weapp.html