最近参加了几次面试,有面试官问到了这类问题:微信小程序比h5的优势是什么,为什么小程序要比h5更流畅,小程序内如何使用h5减少包大小等。
个人而言,不太喜欢这样的问题,首先,面试官的问题可能更倾向于对运行优化或者小程序的原理,而且也不是小程序和原生html的差异,毕竟原生不具备数据驱动等新开发模式,没啥可比性。后面小程序特指微信小程序,h5代表当下流行框架Vue/React。另外原理这个东西,对于2C的业务开发来说只是一个标签罢了,引申来说,涉及到技术选型的问题,这个后面我再说,见字如字,先说说这个差异或者优势的问题。下次再有面试官问我,直接看这个博客就好了,不想赘述了[捂脸]
一、相同点
其实用过一个框架再写其他的,发现也比较好平移,说明在开发模式上,小程序和h5没有太大区别,虽说说两者的使用场景、运行环境、开发工具上有所不同,但从整体来看,共通点也很明显:组件化、异步、数据驱动等,开发过程中也能明显看到:生命周期、自定义属性、模板指令、路由、状态管理等。就像一个对象有默认属性,实例化后对属性进行改写,都是框架工具产物。
二、小程序的特殊之处
1、双线程框架
小程序采用的是一种分离的渲染机制。双线程架构,逻辑层和渲染层是分开的,它们运行在两个不同的线程中,双线程的优势不言而喻,渲染和计算分开,有效提升性能。
- 逻辑层运行在 JavaScriptCore 中,负责数据处理和事件处理等逻辑;
- 而渲染层则运行在 WebView 中,负责页面的渲染。
- 这两个线程通过一个数据桥进行通信,JS线程将需要渲染的数据发送到渲染线程,然后由渲染线程根据这些数据来渲染页面。
- 性能提升 由于小程序的渲染过程并不依赖于JS,因此即使JS线程发生阻塞,页面的渲染也不会受到影响。这种机制有利于提高渲染效率,减少卡顿,提升用户体验。
- 小程序由于不支持直接操作DOM,因此所有的页面更新都是通过数据驱动的,这使得代码更为简洁,易于维护。
因为渲染层和逻辑层分离,所以js(逻辑层)不能直接访问dom(渲染层)。渲染层和逻辑层由两个线程管理,逻辑层采用JSCore运行js代码,渲染层使用 webview进行渲染。小程序有多个页面,所以渲染层存在多个webview。两个线程之间由Native 层之间统一处理,无论是线程之间的通信,还是数据的传递,网络请求都是由Native层做转发。
- 渲染线程主要负责页面的渲染工作,包括解析和展示HTML、CSS以及处理用户的交互事件(如点击、滑动等)。在小程序中,渲染线程通常是在Webview中运行的,这使得小程序能够利用Web技术进行页面的渲染。
- 逻辑线程则主要负责处理应用的逻辑,包括处理API调用、请求数据、处理数据等。在小程序中,逻辑线程通常是在JSCore中运行的,这使得小程序能够利用JavaScript来编写应用逻辑。
2、组件组织框架
1)Exparser是微信小程序的组件组织框架,内置在小程序基础库中,为小程序提供各种各样的组件支撑。Exparser的组件模型与WebComponents标准中的Shadow DOM高度相似。
- 基于Shadow DOM模型:模型上与WebComponents的ShadowDOM高度相似,但不依赖浏览器的原生支持,也没有其他依赖库;实现时,还针对性地增加了其他API以支持小程序组件编程。
- 可在纯JS环境中运行:这意味着逻辑层也具有一定的组件树组织能力。
- 高效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺寸也较小。
2)小程序中的部分组件是由客户端创建的原生组件,并不完全在Exparser的渲染体系下:input(focus下表现为原生组件)、canvas、map、textarea、video、camera、live-player、live-pusher
- 扩展Web的能力。比如像输入框组件(input, textarea)有更好地控制键盘的能力。
- 体验更好,同时也减轻WebView的渲染工作。比如像地图组件(map)这类较复杂的组件,其渲染工作不占用WebView线程,而交给更高效的客户端原生处理。
- 绕过setData、数据通信和重渲染流程,使渲染性能更好。比如像画布组件(canvas)可直接用一套丰富的绘图接口进行绘制。
3、系统权限
这里的系统权限可以理解为相对较高的隐私级别,如通讯簿,或者可以调用硬件,如蓝牙功能。从这个角度来看,H5本身几乎没有系统权限。虽然有摄像头等接口,但严重依赖浏览器能力,兼容性有限。
而小程序,由于依赖微信客户端本身,所以微信小程序团队向小程序环境开放了客户端的许多能力,当然,前提是你也授权微信相关能力,如允许访问麦克风、允许访问相册等。
4、用户体验 – 硬件支持
深度集成,可以直接使用微信的支付、分享、登录等功能,这些都是浏览器无法提供的。这种深度集成使得小程序可以提供更完整和一致的用户体验。H5应用则主要依赖于浏览器提供的标准Web API,无法直接访问设备的某些功能或特定APP的功能。
硬件优化,充分利用了手机硬件的特性。例如,小程序可以调用设备的GPU进行加速渲染,提高了页面的绘制速度。此外,微信小程序还支持原生组件,可以使用类似原生应用的UI控件,进一步提升了交互体验。
兼容性,由于每个小程序平台(例如微信、支付宝)都有自己的API和规范,所以一个小程序可能需要针对不同的平台进行适配或修改。此外,小程序也需要考虑不同的设备和操作系统,例如不同的手机型号、屏幕大小、系统版本等。
5、用户体验 – 资源加载
资源缓存,小程序设计原则之一就是“局部性原理”,即常用的资源会缓存在本地,这就意味这你在进入小程序后,后续的访问和操作都会减少很多加载时间。
离线访问,小程序在首次打开时会下载必要的代码和资源文件到本地,因此在后续的使用中,即使没有网络连接,也能够运行基本的功能。此外,由于核心代码和资源文件都保存在本地,这也可以减少加载时间,提高运行效率。
热启动,当用户离开小程序或者切换到其他应用,小程序就会被挂起或关闭。如果用户在短时间内回到小程序,通常可以直接恢复之前的状态。
6、渲染引擎
微信小程序和H5页面在渲染方式上存在一定的差异,这直接影响了用户感知的流畅度。微信小程序采用了更轻量级的渲染引擎,如基于WebAssembly的小程序渲染引擎(WxRender)。这种渲染引擎可以在浏览器内部直接编译运行,避免了复杂的DOM结构和JavaScript解析,从而提高了渲染效率。
相比之下,H5页面通常使用浏览器的标准渲染引擎,其在渲染过程中可能需要处理更复杂的HTML和CSS结构,以及多样化的JavaScript交互。这使得H5页面的渲染过程相对较重,可能影响用户体验的流畅度。
这里你可能有疑问,为什么WebAssembly或者WxRender的引擎要比浏览器的好。简单从源头上说,浏览器是为了展示内容,前者则是为了做图像处理,就需要比浏览器更注重渲染。本质原因是,WebAssembly是一种可以在浏览器运行的二进制代码,体积更小、解析更快、更好的利用cpu等。这块不是本文重点就不做赘述了。
现在微信推出了新的渲染引擎Skyline,提供了更好的性能优化:单线程版本组件框架、组件下沉、长列表按需加载、wxss预编译、样式计算更快、内存占用更少。实验数据统计,Skyline比webview的首屏时间缩短66%,内存减少35%。
7、更新机制
更新后抛开CDN/浏览器缓存啥的,h5基本上更新结束刷新就可以看到效果。
前面讲到小程序的缓存和热更新,小程序的更新在冷启动的时候会做版本检查,如果有更新会重新下载并替换本地包代码。同时小程序平台通常支持增量更新,即只下载变更部分的代码,这可以减少下载时间和流量消耗。其他的像预下载、静默更新等都可以提升用户体验。
另外小程序后台支持控量发布更新,可以更好的容错和回归。
三、关于技术选型
最后我们再来说下这个技术选型。我在之前的业务中有做过这类考量,比如用原生还是h5,h5用vue还是react,h5用原生还是多端同构的工程。以下是几个维度:
1、业务需求决定可选范围:首先并不是单纯根据他们的性能来进行技术选型,更多的是业务的实际需求。就像当初大家做小程序不是因为技术,而是因为小程序本身的社交属性和庞大的用户群体,当时一顿肆虐的无良推广,如今各种限制和收割,不得不说龙哥好大一盘棋。
2、用户体验优先:回归到技术范畴,选型看效果,h5体验相对差一些,做完后给产品,可能会被dis,所以优先选择实现效果好的。
3、满足业务降低开发成本:当然也会有特殊情况,比如有一些技术限制,或者开发成本巨大,不得不降级,比如之前做医保交易链路,h5效果不好,但是需要注意,这个业务注重的是实现,体验并不是最重要的,而且h5跨平台,实现简单,如果原生、小程序都做开发,那想上线你且排着吧。
4、项目维护性和扩展性:举几个不恰当的例子,纯原生html+js写的页面肯定没有用框架好维护;如果团队都是写vue的,你非要用react写,对后面维护也会有成本;用框架写可能没有用多端同构写的好扩展,但是如果你们的多端同构不够健全的话另说了。
5、性能:这个比较隐性一点了,我们常说比较大型的管理后台比较喜欢用react,一般toC都会选择vue,这个需要考虑的就是框架本身的
因为我我们本来就是小程序业务,如果不是包大小实在不行了,也不会考虑用h5,而对于一个h5来说,必然需要的是一个了浏览器,虽然可以嫁接到小程序,但是一般也不会刻意这么搞。