阅读 598

【小程序进阶】上篇:分析小程序的设计方案,优劣势,以及如何技术选型

前言

好久不见的掘友们。一起聊聊小程序话题。

还记得,早期移动端的战场上,web与app还在借助自己各自优势占据市场。在这两种方式的优劣势较明显还未分出高低的情况下,腾讯优先推出一个很巧妙的方案,那就是介于web与app之间的小程序。

记得当时推出即火爆,特别针对中小企业,成为客户端的优先方案,一年内就占据了移动端的重要市场。陆续很多有着自己粘性的app都推出了自己小程序,此外还有快应用等等,也间接的反馈出"微信小程序"模式的成功。

回顾时间点,没记错应该是2017年头正式开启小程序,然而当时从技术或者是市场定位的角度,并不是特别成熟。从业务角度出发,当时只支持五个页面栈,也还未与分包等模式,对业务的限制是挺明显的。再从技术的角度,还记得开始时连ES6都不支持,也没有组件开发模式(最开始好像只有"模板")。后续的节奏,可能落后于web,但也算一步一步的更新过来了。

那么,从当前技术的角度,小程序是怎么样的?带着问题,一起分析小程序。

章节

小程序系列共有三个章节,本文为第一章节:

上:分析小程序的设计方案,优劣势,以及如何技术选型。

中:如何优化自己的小程序框架(工程化)。

下:如何将web或者第三方,转为原生小程序(babel)。

小程序的设计方案

这里,我们一起分析小程序各方面的设计,从官网入手,一步一步走近小程序。

1)小程序的交互设计

首先,我们先聊聊小程序的交互设计,即渲染层与逻辑层的交互。从官网的资料我们可以了解到,小程序并不是一个独立的webview玩法。反而,更接近react native,或者是flutter的设计理念。这个设计理念就是,逻辑层与展示层分开,通过中间JSBridge或者是其他存储技术,或者Native本身,完成两者的通信,形成一个逻辑与展示的互相驱动。

借助一下来自官网的图例:

image.png

从图例我们更能理解这里的通信:小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端做中转,逻辑层发送网络请求也经由Native转发。

WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。

那么这样设计的好处是什么?这是一个值得思考的问题,下边一起揭晓。

参考文档:developers.weixin.qq.com/miniprogram…

2)小程序的运行环境

还记得曾经有人问过我一个问题,为什么小程序不能在浏览器先跑起来?其实如果看了小程序的运行环境,就能明白其中的原因。

借助一下来自官网的图例:

image.png

从上述可以看出,小程序的逻辑层,在IOS中是使用JavaScriptCore为宿主环境,而在安卓中,使用了V8引擎。就连渲染层,都属于定制的内核。这中间不妨包含很多微信内部的封装。

开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。

而App Service,是要依赖于微信客户端定制内核的webview才能执行。看到这里,你是否了解为什么小程序无法在浏览器运行?

即使是在微信自带的开发工具上开发,都无法完成跟客户端一模一样的体验。这里微信只是模拟客户端,搭建了一个NWJS环境方便开发调试,看到这里,你是否明白,为什么安卓小程序,IOS小程序会有一些差异?或者为什么本地开发时,一些功能不可使用。

那么这样设计的好处是什么?这还是一个值得思考的问题,下边一起揭晓。

参考文档:developers.weixin.qq.com/miniprogram…

3)小程序的js兼容

在一些非专业的前端人员的眼中,似乎小程序写的就是跟web端一模一样的js。其实这里还是存在一些差异。个人的观点,小程序的js标准,是慢一拍的。

从es6开始就已经慢了一拍。如今web的框架,基本都已经开始支持es10或es11了,但小程序你想使用,还是得自己写转义,这个成本就比较大了。

此外,由于微信自定义内核的原因,它的确是有很多因素无法抹平。

借用官方的原话:


尽管各运行环境是十分相似的,但是还是有些许区别:

  • JavaScript 语法和 API 支持不一致:语法上开发者可以通过开启 ES6 转 ES5 的功能来规避(详情);此外,小程序基础库内置了必要的Polyfill,来弥补API的差异(详情)。
  • WXSS 渲染表现不一致:尽管可以通过开启样式补全来规避大部分的问题,还是建议开发者需要在 iOS 和 Android 上分别检查小程序的真实表现。

参考文档:developers.weixin.qq.com/miniprogram…

4)小程序的单位

开发小程序的掘友都知道,小程序在单位上,使用的是跟其他客户端不一样的rpx。而且,貌似一般的开发,不会像web端一样,还需要做一些适配工作。

这里笔者觉得也非常好理解,wxss其实也是一个类scss或者less的预编译语言。而rpx,最终也由某种规则,转换成px(当前是webview,未来如果用原生渲染,也可能是原生的dp。)

至于这个转换规则是什么,我们也可以一起看看官网的图例:

image.png

参考文档:developers.weixin.qq.com/miniprogram…

5)小程序的分包

由于小程序自身大小的限定,每个包的大小为2M。某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。

其实这点,即使不是小程序,web端我们一样是需要考虑这方面的问题。当项目慢慢变大时,我们就得考虑首次初始化的问题。

其原理相关文档,笔者暂时没找到官方。但是也可以勉强猜测一下:利用import或者require,根据配置的pages.json,把同一个包对应的驱动js生成同一个js文件。而在客户端使用时,用到哪个包,就先下载哪个包对应的js包。从而达到分离的目的。

这里,小程序还实现分包预加载与分包异步化(不成熟),有兴趣可遇了解到。

值得一提的是,这里有个小坑:require/import的任何文件,只要不在同一个目录下面,都不会被打进分包,也就是说,类库及一些公共文件,只能放在主包里面,如果主包分包划分不好的话,主包的大小也很难降下来

参考文档:developers.weixin.qq.com/miniprogram…

6)小程序的数据储存

  • storage

类似浏览器的localstorage。值得注意的是异步的,如果需要同步需使用setStorageSync。常用于需要长久存储的数据,如用户登录信息。

参考文档:developers.weixin.qq.com/miniprogram…

  • app.globalData

可以将数据存储在globalData。常用于初始化数据。如服务器时间等,globalData是个不错的选择。

  • wx挂载

我们也可以将数据挂载在wx对象中。

7)小程序的通信方式

笔者列举一下笔者了解到的通信方式,欢迎补充。

  • 上下页面通信

可以通过路由带参数,在onLoad方法接受上一级参数。

  • 父子组件通信

父子组件通信,可以通过properties交互,这里就是vue或react的props,只是换了个名称。

  • 子父组件通信

相信vue的伙伴们,第一时间想起emit。同理,小程序的triggerEvent就是类比$emit;

  • 选择节点

很多时候,我们需要制定组件更新,即是vue的ref。同理,小程序也提供了this.selectComponent绑定id,然后可以获取到对应的节点。

此外,还有this.selectOwnerComponent。类似vue的this.$parent。

  • 页面栈通信

类似浏览器,貌似页面栈无法更新。而小程序的设计,因为每个页面是独立于webview的存在,是可以与其他的页面栈产生通信的。

可以通过getCurrentPages() 拿到所有的页面栈,数组最后一个为当前页面栈,如需修改上一个页面栈的data,只需修改数组倒数第二个data,以此类推。

  • 存储数据通信

我们还可以利用存储数据进行通信,这里可以参考上边"小程序的数据储存"。值得一提的是,setStorage是异步的,同步需要setStorageSync。

  • 状态管理器

类似vue有vuex,react的react-redux。个人觉得没有什么必要。但如果需要,官方还是有相似的插件:developers.weixin.qq.com/miniprogram…

  • eventBus

小型eventBus,在小程序也是可行的。可参考EventBus原生写法。

8)小程序的混入方式

常见的项目,基本都有自己的混合方法引入。例如vue的mixin,或者是react的高阶函数。

而小程序也有自己的behaviors。值得一提的是,当前只有Component能使用,Page并不支持。

那么如何越过这个问题呢?笔者的观点是,Component也支持抒写页面,且有更高的扩展性,不妨用Component替换原来的Page,那就可以达到全局都可以使用behaviors的目的。

此外,自定义组件可以通过引用内置的 behavior 来获得内置组件的一些行为。

例如可用behaviors: ['wx://form-field'],来继承微信原有的表单功能。

参考链接:developers.weixin.qq.com/miniprogram…

9)小程序的控件

跟HTML 5一样,小程序本身也自带了一系列内置控件。如input,radio等。

在部分开发眼中,它更像一个UI库,基于webview对对应的html控件进行二次封装。可以这么理解,但并不是所有控件都设计如此。

例如笔者了解到一些用到原生的控制:如webview, cavnas,video,map,textarea。

这也解释了,为什么有些style不会生效。

Native 实现的组件会遮挡其他组件,优先级比其他的高一些。

参考链接:developers.weixin.qq.com/miniprogram…

10)小程序的网络请求

由上边通信原理可知,逻辑层发送网络请求也经由Native转发,跟浏览器直接发起并不一致

其中,还比较特殊的是:

  • 1)小程序需要配置域名校验,这比浏览器多了一层限制。
  • 2)小程序并不支持http2,目前只支持http1.1
  • 3)小程序的网络请求,并发比浏览器多一些,最大并发限制是 10 个。

参考链接:developers.weixin.qq.com/miniprogram…

11)小程序的npm

终于跟上时代了,支持npm。

但是此npm,非彼npm,它只支持小程序源的npm,无法使用其他源。

我们需要,先建立一个打包项目,发布到本地。才能实现本地其他项目的应用。

参考链接:developers.weixin.qq.com/miniprogram…

12)小程序的"脚手架"

类似vue-cli,umi等脚手架,都自带一系列的默认工具。

这里也简单提及一下小程序的"脚手架"。例如类似webpack-bundle-analyzer的依赖分析,类似jest的自动化工具等等,这些都已经是微信自带的工具。

参考链接:developers.weixin.qq.com/miniprogram…

developers.weixin.qq.com/miniprogram…

小程序的优劣势

上述章节已经分析了小程序与web的区别,以及各方面设计。这里继续往下分析小程序的优劣势。(这里仅从技术角度出发,至于微信自带流量,微信体系等,不在技术领域内)。

以下仅为个人观点,我是掘金,逐步前行。

1)优势

  • 优势1:更快速的加载,性能优势

    这点从上述的分析,我们就可总结出:

    1. 混合原生,小程序的展示,属于原生与webview的混合,原生的组件,毫无疑问比webview的有优势。

    2. 加载快web端,在资源加载的时候,必须把相关驱动加载进来。如vue双向绑定,如何驱动肯定需是要打包到页面上执行。而小程序,已经内置在Native层,这样页面只关注与逻辑代码。省下了空间,当然加载速度更胜一筹。

    3. 多线程。在web开发中, 渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应。而小程序,巧妙的将他们分别运行在不同的线程中,这样就不会互相影响。特别是针对首屏,优势会更加明显。

  • 优势2:web资源离线存储

    借助官方的原话: 微信 Web 资源离线存储是面向 Web 开发者提供的基于微信内的 Web 加速方案。 通过使用微信离线存储,Web 开发者可借助微信提供的资源存储能力,直接从微信本地加载 Web 资源而不需要再从服务端拉取,从而减少网页加载时间,为微信用户提供更优质的网页浏览体验。每个公众号下所有 Web App 累计最多可缓存 5M 的。

    当然,web端本身也有缓存。

  • 优势3:强大的原生能力,拍照,蓝牙,客服等。

    普通浏览器web,有很多不可能完成的功能。如打开蓝牙,拍照等。但在微信浏览器,一开始微信引入了JS-SDK。JS-SDK说白了,就是对的 WeixinJSBridge 的一个包装,以及新能力的释放。

    而小程序中,直接将JS-JDK内置在api中,而且扩展了一些,使得小程序的原生能力更加强大

  • 优势4:丰富的生态资源

    上述提到,小程序"脚手架",也引入了部分工具。然后,还包含了很多比vue-cli更强大的生态工具,如数据开放,性能分析,单元测试,实时日志,消息推送,直播,第三方小程序(如物流助手,开票助手)等。

  • 优势5:支持云开发

    对于小应用来说,或者是单一能力的开发者来说,这的确是一个福音。只需一个客户端,就可解决一个应用,无需服务端。小程序的云开发,也逐步强大了起来。

  • 优势6: 强大的sass体系

自带的托管第三方开放平台。可能很多掘友们没使用过。类似"有赞"上万个应用的开发,小程序的托管模式可解决。

  • 优势7: 无需兼容性

    上述"小程序的单位",已说明。

2)劣势

谈完好的方面,再来看看不友好的方面:

  • 劣势1: 慢一拍的前端节奏

    es6, npm,typescript等,如今支持的标准不一致,但总算支持了。但这些,是慢一拍的节奏引进。在web端"火爆"一两年后,小程序才逐步引入。

    就如当前,web已经支持es10,es11,而小程序你想支持,不好意思,你得自己先折腾。官方估计还要一段较长的时间。

  • 劣势2:  ECMAScript 标准的支持存在差异 

    就如:Promise存在时差,babel-polyfill不支持等。可参考文档:developers.weixin.qq.com/miniprogram…     

  • 劣势3: 过度依赖微信的底层。

    想象长期开发小程序的小伙伴都遇到过"坑"。无法解决,只能等官方修复。这就是过度依赖微信底层的结果。

  • 劣势4: 非浏览器标准。

    例如:不支持http2,我们不能已标准的浏览器标准来要求小程序。

  • 劣势5: 小程序自身的限制条件。

    如包大小,审核机制,各种资质,页面栈不能超过10个等,这些经常成为开发,或者是业务上的障碍。

小程序的开发模式

1)第三方转义打包模式

这种开发模式,并不是小程序的出现才有的。在6~7年前,市场就已经出现了hybird app的概念。后续的hybird已不再有当年的火爆,他们很多都转战"小程序"。如uni 1.0版本,后续升级为uni 2.0版本(vue模式)。

首先我们来看看,曾经有一席之地的小程序第三方框架

  • WePY - 支持组件化的小程序开发框架,腾讯原生框架
  • mpvue - 基于 Vue.js 的小程序开发框架,从底层支持 Vue.js 语法和构建工具体系
  • Taro - 使用 React 的方式开发小程序的框架,同时支持生成多端应用,京东研发
  • uni-app - 使用 Vue 语法开发小程序、H5、App的统一框架
  • chameleon - 一套代码运行多端,一端所见即多端所见,滴滴研发
  • megalo - 基于 Vue 的小程序开发框架,网易考拉研发
  • kbone - Web 与小程序同构解决方案,腾讯研发
  • ...

这些是笔者曾经了解过的,还有很多较小的平台更数不胜数。然而,在今天占有率已经大大的减少。类似曾经风靡的mpvue,也早早宣布不维护。

这种开发模式的优劣也相对明显:

优势:

  • 1. 学习成本低

    如react生态低成本进入taro,vue生态低成本进入uni。无语适应,小半小时即可参与开发。

  • 2. 多端编译。

    一份最高支持:h5移动端,各类小程序,快应用等。有些还支持生成app。

  • 3. 自带工程化

    如支持scss,eslint,vuex等。

  • 4. 方法的扩展

    框架基本都对自身对wx.api进行了一次封装。此外还进行了扩展以及修改。如uni实现了data对页面的绑定,不需要再setDate。同理taro也采用了setState的方案。

  • 5. 拓展的组件库

    无论uni,还是taro,或者其他,基本都对官方的ui库进行二次封装,其功能都有自己的特色,或者对其组件进行了扩展。让使用者更好的

劣势:

  • 1. 依赖第三方

    该问题可大可小。特别是非有声望的公司维护的框架,没准过一段时间就不维护了。如几年前比uni更火爆的的mpvue已不维护。不维护的那天,也就意外的着你的项目,重构!

  • 2. 无法调试

    由于本身以及是编译后的文件,此时想再通过端点调试,你甚至不清楚原来写的代码编译后在哪里。

  • 3. 转义效率低

    本身,写完原生小程序代码,就需要编译一下才能才虚拟机上看到效果。而用第三方,还需编译为原生。什么意思?写完代码之后:你的代码(第三方) --》转义为原生(原生)=》再编译让虚拟机允许。这多了个过程,所以效率变低,这是事实。

  • 4. 双平台bug。

    原生小程序的bug,该问题近几年也相对好转,但问题还是依然存在。各大论坛搜索"小程序的坑",总有一堆文章让你体验。然而用第三方,你还要接受第三方的bug。你需要容纳双平台的bug。

    在接受小程序官方的“bug”的同时,还需要同时接受第三方的"bug"。

  • 5. 编译后工程化文件置空

    此外,编译后文件历史等置空的问题。如快速页面读取配置,编译之后又置空。

个人观点:

如需跨终端,的确是一个省钱的方案。再需统一技术栈,低成本进入框架,也是一个不错的方案。

2)webview模式

优势:

  • 1.动态发布

    这点其实很香,直接越过了微信的审核。想什么时候上线,直接更新web服务器即可。

  • 2.脱离微信体系

    这是一个很大的缺陷,同时也是一个很大的优势。脱离了微信的体系,那也意外着只是一个webview的展示。这时候也已经脱离了微信本身,不再受一些展示性的限制之类。

  • 3.开发调试脱离

    此时也已经是H5页面,开发也可以直接在常规浏览器调试,无需依赖微信调试工具。

劣势:

  • 1.首次加载较慢

    小程序是借助了微信本身内部的封装,而H5是完完全全自己的实现。所以,毫无疑问,同样的功能,H5文件是更大的。这也是为什么说首次加载较慢。

  • 2.无法调用微信api。

    已经脱离微信的体系,那也意味着小程序的一切功能,都无法使用。如分享,支付,统计等。

  • 3.无法有原生功能

    同2,所有原生功能寄托在微信中间层上,将失效。如蓝牙,拍照,获取手机信息等。

  • 4.一些小坑:

    如官方的提醒:在 iOS 中,若存在JSSDK接口调用无响应的情况,可在 web-view 的 src 后面加个#wechat_redirect解决。

个人观点:

小公司内部系统使用小程序,可以采用该模式。或者是一些展示型的模块,可以采用webview的形式进行开发。事先要考虑清楚,自己的页面能否完全不使用微信的api。

3)纯原生开发模式

优势:

  • 1.性能最优。

    启动,调试,打包,加载资源等,一切基本的编译,毫无疑问最快。因为相比只是,少了很多辅助性的编译时间。

  • 2. 拥有微信功能第一资源。

    如可视化,热更新,性能检测等,这些都是其他方式无法享受的小程序福利。

    1. 调试清晰

    无论是样式的定位,或者是具体js的代码定位,原生的更能快速定位到问题。

劣势:

  • 1. 扩展能力弱。

    不支持scss,自定义eslint等。也不支持npm的导入(此npm非小程序的npm)

    1. 写法不友好。

    1)单向绑定,没有双向便捷。而方式较独立,与常用的框架不一致。

    2)方法不支持直接传递参数。只能通过data-id的方式传递参数。写法跟常用前端框架不一致且相对较繁琐。

    1. 文件较多

    这里对比其他框架,无论vue还是react都可以用一个文件,解决html + js + css。而小程序需要4个文件来支持,有时候项目大了显得特别的繁琐。

个人观点:

市场最常用的方式。是相对稳定,以及相对成熟的做法。当然,如果能自己再优化一下,那就更好了。

4)简单工程化模式

可以在原生的基础上进行优化,改进纯原生模式的不友好的地方。

如,支持SCSS,支持自定义eslint以及格式化,支持监听this.data驱动视图等优化。该部分为一下章节重点。

结语

本文分三个章节。下一章节,如何优化自己的小程序框架。

此外,文章不足之处,欢迎指正或建议。

文章分类
前端
文章标签