微信小程序的运行态环境
WebKit的发展历程
粗略地说,Webkit = WebCore + JavaScriptCore, Chromimum = Blink + V8
1998,自由软件社区KDE开发了HTML渲染引擎KHTML和JavaScript解析引擎KJS,也就是现代浏览器两个重要的引擎,其中:
- 渲染引擎(layout engineer 或者 Rendering Engine)
负责渲染引擎负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。 - JS 引擎
负责解析 Javascript 语言,执行 javascript 语言来实现网页的动态效果。最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎。
当时还存在多个浏览器内核相互竞争,包括:Trident(IE),Gecko(firefox),Webkit(Safari chrome 等)以及 Presto(opera)。
2001年,Apple公司的开发者Don Melton于在KDE的基础之上开始了WebKit项目,KHTML被命名为WebCore,KJS被命名为JavaScriptCore。因此,对于Apple的产品来说,浏览器内核就是WebKit,即渲染引擎采用的是WebKit内核。
2008年,Google为发展浏览器Google Chrome而开启了免费开源软件项目Chromium,其JavaScript解析引擎采用Google自己开发的大名鼎鼎的V8引擎,渲染引擎仍然采用WebKit内核。Google使用Chromium代码来制作其Chrome浏览器,该浏览器比Chromium具有更多功能。。
2013年,Chromium项目将渲染引擎替换为Blink引擎,并在Chrome28及后续的版本上采用。随后 opera 则放弃了自主研发的 Presto 引擎,投入谷歌怀抱,和谷歌一起研发 blink 引擎,国内各种 chrome系的浏览器(360、UC、QQ、百度等等)也纷纷放弃 webkit,投入 blink 的怀抱。
2018年,微软宣布Microsoft Edge未来也将基于Chromium开发。
WebView是什么
WebView是一个基于webkit引擎、展现web页面的控件,是iOS SDK或Android SDK的一个重要组件,其本质就是一个高性能webkit内核浏览器。
WebView的功能主要包括:
- 显示和渲染Web页面
- 直接使用html文件(网络上或本地assets中)作布局
- 与JavaScript交互调用
iOS、MacOS的WebView
顾名思义,WebView是与浏览器密切相关的开发组件。Apple作为封闭型生态系统,Safri是默认浏览器,iOS APP的WebView也是其强制标准,应用开发者完全没有选择权。
UIWebView是Apple在iOS 2推出的“老”资格页面渲染引擎。- 从iOS 8起,Apple推出了
WKWebView,并作为Safri的默认渲染引擎,但开发者也可以通过manifest配置项选择使用UIWebView。 - 从iOS 13起,Apple将
UIWebView列入非公开api,2020年4月起App Store将不再接受使用UIWebView的新App上架、2020年12月起将不再接受使用UIWebView的App更新。
相比UIWebView来说,WKWebView的性能更好,节省内存,支持了更多的 HTML5 特性。
此外,存在的主要缺陷有:
- 不支持websql(iOS8、9上不支持,iOS10恢复支持)
- 不支持plus.navigator.setCookie
- 不支持webview的overrideresource方法
- 不支持js原生加密
- 在联网及本地文件读取等有各种跨域限制、
Android终端的WebView
Android Webview的进化历史如下:
- Android 4.4以前,自带WebView是Android webkit 内核,很多HTML5标准语法不支持,比如indexeddb、webgl等,canvas性能非常差
- 从Android4.4系统开始,自带WebView变成了chromium 30内核,Chromium内核(Blind + V8)取代了Webkit内核
- 从Android5.0系统开始,webview脱离ROM可单独更新,成为一个独立的apk,可以不依赖系统而独立存在和更新。
- 从Android7.0 系统开始,如果用户手机里安装了 Chrome , 系统优先选择 Chrome 为应用提供 WebView 渲染。
- 从Android8.0系统开始,默认开启WebView多进程模式,即WebView运行在独立的沙盒进程中。
Android作为开放式生态系统,尽管Chrome是默认浏览器,但由于其内核是Chromium,其开发SDK也能支持第三方Chrome家族浏览器。
由于政策环境的影响,几乎所有国产品牌Android都提供自己的浏览器(虽然都是基于Chrominum内核),从chrome 37一直跨度到60,手机用户侧使用了到底是哪个版本是不一定的,因此WebView的运行环境就很复杂了
Window终端的WebView
在很长一段时间里,Windows 10用户对 Microsoft Edge 的印象都停留在「Chrome 下载器」这个层面上,即便 Edge 本身相比 Internet Explorer 有着诸多优点,孱弱的扩展生态和巨大的迁移难度还是让不少用户望而却步。
2018 年年底,基于 Chromium 内核的 Microsoft Edge 正式立项。微软的壳、Chromium 的心, 微软彻底放弃自己开发的EdgeHTML内核,解决 Edge 一直以来都难以解决的兼容性问题(在 EdgeHTML 下不少传统网页都无法正常显示)并融入现有的 Chromium 生态。
因此,Window Client的WebView至此已经与Chromium完全一致了!!!
微信小程序的Runtime
小程序无论从技术上还是从理念上都不是一个新事物:从技术上讲,它借用了React Native的一些概念,定义了一套微信自有的组件并根据运行环境的不同(PC、iOS、Android)将这些组件编译/转化为对应平台的可运行组件;从理念上讲,百度早年的“轻应用”、QQ右下角的“应用宝”还有支付宝里的各类小服务,早已是小程序的雏形。
小程序的宿主环境
小程序的主要开发语言是 JavaScript,其开发模式与 web 开发类似,都是使用 javascript 进行开发,使用 css 控制样式,最终渲染使用 html 进行渲染。
在小程序中,渲染层通常与逻辑层分离。
- 渲染层
WXML模板和WXSS样式工作在渲染层。渲染层的界面使用了WebView 进行渲染。
由于一个小程序通常存在多个界面,所以渲染层可能使用多个WebView线程
View 负责渲染小程序页面,包括 Web 组件和原生组件渲染,可以将其视为混合渲染。例如,Web 组件渲染可以由 WebView 处理,但 WebView 不支持某些 Web 组件渲染,或者是性能受限;小程序还依赖于某些原生组件,例如地图、视频等。 - 逻辑层
JavaScript脚本工作在逻辑层,采用JsCore线程运行JS脚本。
Service 是用主要用于执行小程序的 JS 逻辑。主要负责小程序的事件处理、API 调用和生命周期管理。扩展的原生功能通常来自宿主原生应用程序或操作系统,这些功能包括拍照、位置、蓝牙、网络状态、文件处理、扫描、电话等。它们通过某些 API 调用。当小程序调用原生 API 时,它会将 API 调用传递给扩展的原生功能,以便通过 JSBridge 进一步处理,并通过 JSBridge 从扩展的原生功能获取结果。Service 为每个 Render 建立连接,传输需要渲染的数据以进一步处理。
视图层和逻辑层分离,两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,这种结构有很多好处:
- 方便多个小程序页面之间的数据共享和交互。
- 在小程序的生命周期中具有相同的上下文可以为具备原生应用程序开发背景的开发人员提供熟悉的编码体验。
- Service 和 View 的分离和并行实现可以防止 JS 执行影响或减慢页面渲染,这有助于提高渲染性能。
- 因为 JS 在 Service 层执行,所以 JS 里面操作的 DOM 将不会对 View 层产生影响,所以小程序是不能操作DOM结构的,这也就使得小程序的性能比传统的 H5 更好。
jsCore的运行环境
微信小程序可以运行在多种平台上:iOS(iPhone/iPad)微信客户端、Android 微信客户端、PC 微信客户端、Mac 微信客户端和用于调试的微信开发者工具。
各平台脚本执行环境以及用于渲染非原生组件的环境是各不相同的:
| 运行平台 | 页面渲染引擎 | JS解析引擎 | 备注 |
|---|---|---|---|
| iOS APP | WKWebView | JavaScriptCore | Apple的强制标准 |
| Android APP | 腾讯自研XWeb | V8 | 基于BOM的碎片化问题 |
| MacOS Client | WKWebView | JavaScriptCore | 与iOS完全一致 |
| Window Client | Chrome | Chrome | |
| 开发者工具 | Chromium Webview | NW.js | 自定义 |
node-webkit(NW.js),是node.js和webkit的结合体,webkit提供DOM操作,node.js提供本地化操作;且将二者的context完全整合,可在HTML代码中直接使用node.js的API。
微信、支付宝、头条等头部APP纷纷打造自己的小程序生态,基本方案都是基于chromium改造的浏览器内核,但基线版本有所不同,例如支付宝基于chrome 57/69等版本,百度基于chrome 63,头条基于Chrome 62等。
X5 渲染引擎
腾讯浏览服务是致力于优化移动端webview体验的整套解决方案。该方案由SDK、手机QQ浏览器X5内核和X5云端服务组成,腾讯X5内核在腾讯家的很多产品使用,包括微信,QQ,QQ浏览器。
腾讯浏览服务 TBS 在 2.3 版本中,其 X5 内核就是基于 Android 5.0 WebView Blink内核(M37版本)定制优化。
从微信6.1版本起,android用户全部使用的QQ浏览器的X5内核。
5.4-6.1之间的版本,若用户安装了QQ浏览器就是使用的X5内核,若用户未安装浏览器,使用的是系统默认内核。
x5浏览器内核的UA特征字符串是:Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044903
XWeb 渲染引擎
大概从2020年起,微信团队放弃了X5内核,自研并默认更换为XWeb内核,其UA特征字符串是:Chrome/67.0.3396.87 XWEB/882 MMWEBSDK/190506
同时,JS引擎也从基于 Mobile Chrome 57 内核的X5,改为基于 Mobile Chrome 67 内核的V8引擎。
恭喜微信团队,终于回到了Google标准的道路!!!
附录一:关于如何查看Android手机端webview的版本
- 日志里查ua
- 在系统设置里找到所有应用,显示隐藏系统进程,在里面找到Android system webview,显示的版本即为chrome版本。
Android手机默认浏览器和webview的区别
国外品牌的安卓手机,自带浏览器就是chrome。而国内安卓手机,自带浏览器大多是QQ浏览器、UC浏览器的贴牌,极个别是自己改造chromium。
所以手机自带的浏览器并不等于webview,在一个平台可运行,不代表另一个平台可兼容。
QQ、UC、360等浏览器也基本是基于chromium做改造,不同版本的浏览器其使用的chromium内核版本也不一样。具体可以打印ua查看。
注意夜神等安卓模拟器的Android版本是4.4,很多新语法都不支持。如果你有影响用户的能力,为了给用户更好的体验,可以引导Android用户安装最新版Android system webview。应用宝、华为、金立等应用市场均可下载这个apk,或者翻墙到google play store。
在华为、小米、金立手机上,wifi下会自动更新Android system webview。
尤其是有些Android5用户使用的Android system webview 37版本,有硬件加速bug,闪屏花屏,此时升级webview即可解决。有人问可否在打包时直接集成新版Android system webview,减少浏览器兼容问题?
webview体积至少50M起,体积实在太大了。有兴趣的开发者可以自己研究离线打包。
倒是可以这样:js里判断当前手机是Android5以上,且webview版本过低,比如低于40(ua可以判断),可以提醒用户是否升级webview,然后引导用户去之前贴出的地址下载更新webview。
但不管怎么样,尽量少写可能遇到兼容性问题的代码。