前言
好久不见的掘友们。利用周末的世界,一起聊聊小程序话题。
还记得,早期移动端的战场上,web与app还在借助自己各自优势占据市场。在这两种方式的优劣势较明显还未分出高低的情况下,腾讯优先推出一个很巧妙的方案,那就是介于web与app之间的小程序。
记得当时推出即火爆,特别针对中小企业,成为客户端的优先方案,一年内就占据了移动端的重要市场。陆续很多有着自己粘性的app都推出了自己小程序,此外还有快应用等等,也间接的反馈出"微信小程序"模式的成功。
回顾时间点,没记错应该是2017年头正式开启小程序,然而当时从技术或者是市场定位的角度,并不是特别成熟。从业务角度出发,当时只支持五个页面栈,也还未与分包等模式,对业务的限制是挺明显的。再从技术的角度,还记得开始时连ES6都不支持,也没有组件开发模式(最开始好像只有"模板")。后续的节奏,可能落后于web,但也算一步一步的更新过来了。
那么,从当前技术的角度,小程序是怎么样的?带着问题,一起分析小程序。
章节
小程序系列共有三个章节,本文为第一章节:
上:走近小程序,了解小程序的开发模式。
中:如何优化自己的小程序框架(工程化)。
下:如何将web或者第三方,转为原生小程序(babel)。
走近小程序
这里,我们一起分析小程序各方面的设计,从官网入手,一步一步走近小程序。
1)小程序的交互设计
首先,我们先聊聊小程序的交互设计,即渲染层与逻辑层的交互。从官网的资料我们可以了解到,小程序并不是一个独立的webview玩法。反而,更接近react native,或者是flutter的设计理念。这个设计理念就是,逻辑层与展示层分开,通过中间JSBridge或者是其他存储技术,或者Native本身,完成两者的通信,形成一个逻辑与展示的互相驱动。
借助一下来自官网的图例:
从图例我们更能理解这里的通信:小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端做中转,逻辑层发送网络请求也经由Native转发。
WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
那么这样设计的好处是什么?这是一个值得思考的问题,下边一起揭晓。
参考文档:developers.weixin.qq.com/miniprogram…
2)小程序的运行环境
还记得曾经有人问过我一个问题,为什么小程序不能在浏览器先跑起来?其实如果看了小程序的运行环境,就能明白其中的原因。
借助一下来自官网的图例:
从上述可以看出,小程序的逻辑层,在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。)
至于这个转换规则是什么,我们也可以一起看看官网的图例:
参考文档: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:更快速的加载,性能优势
这点从上述的分析,我们就可总结出:
-
混合原生,小程序的展示,属于原生与webview的混合,原生的组件,毫无疑问比webview的有优势。
-
加载快web端,在资源加载的时候,必须把相关驱动加载进来。如vue双向绑定,如何驱动肯定需是要打包到页面上执行。而小程序,已经内置在Native层,这样页面只关注与逻辑代码。省下了空间,当然加载速度更胜一筹。
-
多线程。在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. 拥有微信功能第一资源。
如可视化,热更新,性能检测等,这些都是其他方式无法享受的小程序福利。
-
- 调试清晰
无论是样式的定位,或者是具体js的代码定位,原生的更能快速定位到问题。
劣势:
-
1. 扩展能力弱。
不支持scss,自定义eslint等。也不支持npm的导入(此npm非小程序的npm)
-
- 写法不友好。
1)单向绑定,没有双向便捷。而方式较独立,与常用的框架不一致。
2)方法不支持直接传递参数。只能通过data-id的方式传递参数。写法跟常用前端框架不一致且相对较繁琐。
-
- 文件较多
这里对比其他框架,无论vue还是react都可以用一个文件,解决html + js + css。而小程序需要4个文件来支持,有时候项目大了显得特别的繁琐。
个人观点:
市场最常用的方式。是相对稳定,以及相对成熟的做法。当然,如果能自己再优化一下,那就更好了。
4)简单工程化模式
可以在原生的基础上进行优化,改进纯原生模式的不友好的地方。
如,支持SCSS,支持自定义eslint以及格式化,支持监听this.data驱动视图等优化。该部分为一下章节重点。
结语
转眼已经撸了近7K字,再来一个章节,估计要超过掘金1W的限制。故分三个章节。下一章节,如何优化自己的小程序框架。
此外,文章不足之处,欢迎指正或建议。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!