android 微信小程序原理,微信小程序架构原理
前言
昨日看朋友圈,据说有人花钱买star,不知道真的假的?以前以为只是大家开玩笑。今日早读文章由百度EUX@田光宇投稿分享。
正文从这开始~~
微信小程序
微信小程序包含下面四种文件:
js
json 配置文件
wxml 小程序专用 xml 文件
wxss 小程序专用 css 文件
{{ text }}
Page({
data:{
text:"这是一个页面"
},
onLoad:function(options){
// 页面初始化 options为页面跳转所带来的参数
},
// ........
})
微信小程序只能通过其 mvvm 的模板语法来动态改变页面,本身 js 并不支持 BOM 和 DOM 操作。
从开发工具看微信小程序架构
在 mac 端直接解压应用 发现 app.nw 文件夹,即开发工具源码。可以知道该项目由 nw.js 编写; 在 package.json 文件下找到应用入口:app/html/index.html。入口 js 为 dist/app.js 我们可以看到整个编辑器的大致逻辑。
但我们关心的是构建过程,在 weapp 文件夹下存在 build.js 文件。没有找到有用的信息,只看到了 upload 模块,包括对大小限制,上传包命名。
为此怀疑,微信小程序本身和 RN 类似。是在服务端打包成 native 语言的。但是通过,android 边框测试发现,微信小程序根本不是 native 原生内容。且,我们在开发工具上写 微信语法,竟然可以直接预览。说明一定有问题。
原生长这样的
编译过程
继续在 trans 文件夹下发现了编译模板。
transWxmlToJs wxml 转 js
transWxssToCss wxss 转 css
transConfigToPf 模板页配置
transWxmlToHtml wxml 转 html
transManager 管理器
用到的内容:
发现用到了一个模板:app.nw/app/dist/weapp/tpl/pageFrameTpl.js, app.mw/app.dist.weapp/tpl/appserviceTpl.js
wcc 可执行程序,wcc用于转转wxml中的自定义tag为virtual_dom
wcsc 可执行程序,用于将 wxss 转为 view 模块使用的 css 代码,使用方式为 wcsc xxx.wxss
在模板中,我们发现使用了 WAWebview.js 文件,WAService.js文件。 在 transWxmlToJs 中我们发现一段 generateFuncReady 事件的函数。对比注册该事件的函数在 WAWebview.js 中。
我们尝试使用 wcc 对input.xml 文件进行编译。
wcc -d input.xml
生成了一段脚本:
window.__wcc_version__ = 'v0.6vv_20161230_fbi'
var $gwxc
var $gaic =
$gwx = function (path, global) {
function _(a, b) {
b && a.children.push(b);
}
....
通过代码我们发现,调用 $gwx 函数会再生成一个有返回值的函数(前提是 path 填写正确);于是我们执行如下代码:
$gwx("input.xml")("test")
得出如下内容:
{
"tag": "wx-page",
"children": [
{
"tag": "wx-view",
"attr": {
"class": "section"
},
"children": [
{
"tag": "wx-input",
"attr": {
"autoFocus": true,
"placeholder": "这是一个可以自动聚焦的input"
},
"children": []
}
]
}
]
}
这应该是一个类似 Virtual dom 的对象,交给了 WAWebivew.js 来渲染,标签名为 wx-view, wx-input。
WAWebview.js
代码在最一开始提供的是兼容性工具,还有一个 WeixinJSBridge 引入。
接下来是一个 Reporter 对象,它的作用就是发送错误和性能统计数据给后台。
wx 核心对象,包含了 wx 对象下的 api。但是这里的 api 数量远远少于官方的 api 文档数量。
我们可以再代码里面发现,wx 下注册的 api 最终都会调用 WeixinJSBridge 方法,这个方法。应该是在打包的时候端上注入的。然而,我们也可以在 WAServeice.js 中找到该方法的定义。
所以我们得到了一个结论,WAService.js 是编辑器用来接受 wx 方法回调的代码。
wxparser 对象,提供 dom 到 wx element 对象之间的映射操作,提供元素操作管理和事件管理功能。
接都是对 exparser 对象的处理,包括注册 WeixinJSBridge 全局事件,Virtual dom 算法实现,样式注入等。介绍几个组件重要的内容
exparser.registerBehavior 注册组件基础行为,供组件继承。
exparser.registerElement 为各种内置组件,注册模板,行为,属性,监听器等内容
这里我们观察到,组件:wx-video, wx-canvas, wx-contact-button, wx-map, wx-textarea 等 behaviors 都含有 “wx-native” 属性。这是不是意味着,这类组件都是native 原生实现的呢。我们打开边框检查,发现这类组件确实都时原生的组件。
综上,微信小程序的界面有部分组件使用原生方式实现的,Native组件层在WebView层之上。大部分还是用前端实现的,这样解释了微信小程序的一个bug。
因为 scroll-view 是前端实现,在里面使用 native 组件,这样就无法监听滚动了。
WeixinJSBridge
组件是需要数据来渲染的,查看文档我们知道发送请求的 api 为 wx.request;通过上面分析,我么你知道 wx.request 实际调用的是 WeixinJSBridge。现在我们看看 WeixinJSBridge
WeixinJSBridge 真正发送处理数据请求的时这端代码;如果当前环境是 ios, 那么调用 WKWebview 的 window.webkit.messageHandlers.invokeHandler.postMessage。如果所处环境是 android 则调用 WeixinJSCore.invokeHandler(调用的时候,默认会带上当前 webviewID)。
WAService.js
在我们看的 WeixinJSBridge.js 分析中,我们并没有发现前端的通讯实现,路由能力,数据绑定等级制。进一步查看找到了一个 WAService.js 文件。 查看 WAService.js 文件源码:
在代码最开始,跟 WAWebview.js 一样的 WeixinJSBridge 兼容模块
然后是跟 WAWebview.js 一样的 Reporter 模块。
比 WAWebview.js 中 wx 功能更为丰富 wx 接口模块。(剩余的那部分 wx api 都在这里)
appServiceEngine 模块,提供 Page,App,GetApp 接口
为 window 对象添加 AMD 接口 require define
综上,WAService.js 主要实现的功能:
App( ) 小程序的入口;Page( ) 页面的入口
wx API;
页面有的作用域,提供模块化能力
数据绑定、事件分发、生命周期管理、路由管理
到这里我们得出结论,小程序的架构方案:
整个小程序由两个 webview 组成,代码分为 UI 层和逻辑层。UI 层运行在第一个 WebView 当中,执行 DOM 操作和交互事件的响应,里面是 WAWebview.js 代码及编译后的内容。逻辑层执行在(第二个webview 中)独立的 JS 引擎中(iOS:JavaScriptCore, android:X5 JS解析器;统称 JSCore;开发工具中,nwjs Chrome 内核),WAService.js 代码和业务逻辑。
当我们对 view 层进行事件操作后,会通过 WeixinJSBridge 将数据传递到 Native 系统层。Native 系统层决定是否要用 native 处理,然后丢给 逻辑层进行用户的逻辑代码处理。逻辑层处理完毕后会将数据通过 WeixinJSBridge 返给 View 层。View 渲染更新视图。
架构的讨论
微信的这种架构,对逻辑和UI进行了完全隔离,小程序逻辑和UI完全运行在2个独立的Webview里面来处理。那么这么做的好处是啥?总感觉更加麻烦了。除了小程序外,还有人采用这种架构设计么?
在网上搜索了一下,目前使用这种架构的项目还真有一个:去哪儿最新的 YIS 框架
YIS 采取了类似小程序的架构,分为逻辑层和UI层。UI 层运行在 WebView 中,而逻辑层运行在独立的 JS 引擎中。相应地,整个应用的代码,也分为两个大的部分,一部分运行在 WebView 中,一部分运行在JS引擎中。JS引擎计算DOM结构输出给WebView,WebView转发用户的点击事件给JS引擎。
该项目做法和小城十分类似,唯一缺少的就是没有 native 的组件吧。然而官方文档上也没有任何介绍,为什么要这么做,只是说更流畅了。
一些看法
传统 web 页面显示需要经历一下几个步骤:
webview 初始化
加载 HTML, CSS, JS
编译 JS
Render 计算
DOM Path
而利用小程序架构后,我们就可以将上述过程拆解成两部分并行执行: webview 部分:
webview 初始化
加载 HTML,CSS, JS (经过拆分后,体积大幅度减小)
编译 JS
等待页面需要的数据
反序列化数据
执行 Patch
渲染页面
等待更多消息
jscore 部分:
初始化
加载框架 js 代码
编译 js
加载业务逻辑 js 代码
编译 js
计算首屏虚拟 DOM 结构
序列化数据,传输
等待 webview 消息,或者 Native 消息
这样渲染进程和逻辑进程分离,并行处理:加速首屏渲染速度;避免单线程模型下,js 运算时间过长,UI 出现卡顿。 完全采用数据驱动的方式,不能直接操作 DOM,避免低质量的代码。 webview 和 jscore 可以预
当然这种架构方案也有这一定的缺点:
不能灵活操作 DOM,无法实现较为复杂的爱的暖效果
部分和 NA 相关的视图有使用限制,如微信的 scrollView 内不能有 textarea。
页面大小、打开页面数量都受到限制
需要单独开发适配,不能复用现有代码资源。
参考资料
微信小程序底层的实现原理是怎样的
微信小程序架构解析,工作原理解析
微信小程序架构分析
最后,EUX曾分享过:
为你推荐:
android 微信小程序原理,微信小程序架构原理相关推荐
- 编程内功心法「底层原理系列」 底层架构原理,分析CPU处理器鲜为人知的那些秘密
前提概要 所谓,知彼知己百战不殆,针对于计算机的优化技术来讲,最底层也不过是针对于CPU技术的优化了,但是如果要区优化程序,涉及到CPU的执行能力,那必须要了解CPU的原理和概念以及执行过程等概念,所 ...
- 浅析微信小程序的底层架构原理
一.小程序基础知识 小程序是基于WEB规范,采用HTML.CSS和JS等搭建的一套框架,微信官方给它们取的名字:WXML.WXSS,但本质上还是在整个WEB体系之下构建的.WXML说到底就是xml的一 ...
- 小程序商店刷榜_微信小程序游戏跳一跳刷榜原理解析!
最近微信出了一个"跳一跳"的小游戏,这个游戏其实在之前有手机端版本,无奈微信借助强大的用户把这游戏又拿起来弄火了,而且通过最新版的微信可以看出,微信已经开始重视小程序的入口释放了, ...
- 2017年最后一篇文章:微信小程序游戏跳一跳刷榜原理解析!
最近微信出了一个"跳一跳"的小游戏,这个游戏其实在之前有手机端版本,无奈微信借助强大的用户把这游戏又拿起来弄火了,而且通过最新版的微信可以看出,微信已经开始重视小程序的入口释放了, ...
- 教你理解微信小程序的生命周期和运行原理
写微信小程序,他的生命周期不能不知道,不知道小程序就会出现各种bug而无法解决.小助君公众号带你学习小程序的生命周期和运行原理. 小程序由两大线程组成:负责界面的线程(view thread)和服务线 ...
- android用qq浏览器打开微信网页版,QQ浏览器怎么打开微信小程序?
继微信.QQ 之后,QQ 浏览器上也可以使用小程序了. 现已实现与微信小程序打通.QQ 浏览器 Android 版现已上线小程序,在搜索的场景下,小程序嵌入 QQ 浏览器「搜索直达」,作为直接的内容承 ...
- 微信 android兼容性问题怎么解决方案,微信小程序兼容性问题
本文我们来谈谈微信小程序系统兼容性的那些坑. 微信小程序兼容性问题 微信小程序发布一周多了,兼容性问题,特别是 Android 平台兼容性问题特别严重.据我观察,好多小程序掉到兼容性的坑里.掉坑里不要 ...
- 提高微信小程序的应用速度的常见方式有哪些? 小程序怎么实现下拉刷新? 简述微信小程序原理? 小程序的发布流程(开发流程)分析下微信小程序的优劣势?小程序授权登录流程? 小程序支付如何实现
小程序部分常见面试题 提高微信小程序的应用速度的常见方式有哪些? 提高页面加载速度 用户行为预测 减少默认data的大小 组件化方案 分包预下载 小程序与原生App相比优缺点? 优点: 基于微信平台开 ...
- android源码大全 IOS游戏源代码打包下载 小游戏|视频教程 微信小程序源码带后台全套|公众号平台
不断更新中,下面是2017-12-22更新部分 IOS_源码及视频一小部分: 开发环境:Xcode 基于cocos2d的tweejump跳跃游戏ios经典游戏源码.rar https://pan.b ...
最新文章
- 机器学习中的一些概念
- php use include区别,php use和include区别总结
- java欧洲_java欧洲/明斯克时区问题
- 构建Blazor WASM和服务器一体化解决方案
- java同步队列_Java 中队列同步器 AQS(AbstractQueuedSynchronizer)实现原理
- Struts2回顾复习02
- TabBars代码解读之——Visual Studio的自动化接口
- paip.为什么使用多线程的原因.
- 增值税防伪税控系统到底是什么呢?
- java服务安装(三):使用appassembler
- 产品需求文档到底该怎么写?
- 关于360插件化框架Replugin竖屏修改为横屏解决方案
- HDU 5234 DP背包
- JavaScript 中的事件类型2(读书笔记思维导图)
- “庄家”:腾讯的投资“六合彩”
- NTFS下的USN日志文件研究
- Vue使用快速使用Echarts图标以及使用水滴图
- openCV人脸识别简单案例
- QR分解、RQ分解与SVD
- 微信录音amr音频文件转mp3格式
热门文章
- python循环10次怎么写_python循环怎么写
- 中概股周四异动:陌陌大涨18%新浪微博大涨11%
- 分析一下人际界限模糊的定义
- Python 3.X | 一文看懂不懵圈:位置参数(必选参数)、默认参数、可变参数、关键字参数、形参、实参...
- tensorflow分布式框架
- odoo ORM中的filed的关系映射的使用详解1
- Linux下time函数
- 微信小程序[ app.json 文件内容错误] app.json: app.json 未找到解决方法
- DC静态时序分析之时钟篇
- 机器学习: Viola-Jones 人脸检测算法解析(一)