eex对颜色和长度单位支持情况和标准CSS不同,如果程序中使用了weex程序不支持的样式单位,程序运行会出现异常,页面无法正常渲染。
weex demo page
weex支持的样式单位具体如下:
支持以下写法:
.classA { /* 3-chars hex */ color: #0f0; /* 6-chars hex */ color: #00ff00; /* rgb */ color: rgb(255, 0, 0); /* rgba */ color: rgba(255, 0, 0, 0.5); /* transparent */ color: transparent; /* Basic color keywords */ color: orange; /* Extended color keywords */ color: darkgray; }
注意:不支持 hsl(), hsla(), currentColor
6-chars hex是性能最好的颜色使用方式。除非有特殊原因,请使用6-chars hex格式。
在 Weex 中,我们只支持 px 长度单位。
.classA { font-size: 48px; line-height: 64px; }
不支持类似 em,rem,pt 这样的 CSS 标准中的其他长度单位,百分比目前也不支持。
number可用于以下CSS属性:
期H5和Hybrid方案的本质是,利用客户端App的内置浏览器(也就是webview)功能,通过开发前端的H5页面满足跨平台需求。比如PhoneGap cordova ionic ……
该方案提升开发效率,同时也满足了跨端的需求。但有一个问题就是,前端H5的性能和客户端的性能相差甚远。Facebook 推出ReactNative
关于RN,安利下《ReactJS到React-Native,架构原理概述》
Weex与ReactNative 都是基于Yogo渲染骨架做的 跨端框架,一个基于React,一个基于Vue,个人偏好RN,但是Weex 貌似更香。
相对于ReactNative的“learn once write anywhere”,weex的: “write once run anywhere”,牛皮更宽广
关于Weex的使用,还是看官方文档好:https://weex.apache.org/zh/guide/introduction.html
Weex的源文件(最新的Weex版本支持的是Vue文件),如果想用React, 也可以用Rax(兼容React接口), 甚至如果可能,可以支持更多的前端框架。因为根据Weex设计前端框架仅仅是语法层(或者叫DSL), 它与原生渲染引擎是分离的。当然自己扩展支持另一套前端框架也比较麻烦,需要做不少工作。
在初始化阶段, WEEX SDK 会准备好一个js的执行环境。因为我们是要在客户端跑js 代码的,所以需要一个js执行环境,这个执行环境类似于浏览器的v8 引擎, 在IOS 上,则是客户端自带的 js core。
这个js执行环境,可以看成是一个在客户端上的沙盒,或者是一个虚拟机。
为了提升性能,js 执行环境只用在初始化的时候初始化一次,之后每个页面都无须再初始化了。也就是说不管客户端打开多少个weex页面,多个页面的 JS 都是跑在同一个js执行环境中的。
weex-vue-framework 框架 是什么呢?
你可以把 weex-vue-framework 框架当成被改造的Vue.js。语法和内部机制都是一样的,只不过Vue.js最终创建的是 DOM 元素,而weex-vue-framework则是向原生端发送渲染指令,最终渲染生成的是原生组件。
同时,Weex为了提高Native的极致性能,做了很多优化的工作。前端优化性能时,会把业务代码和 vue.js 这类的依赖包分开打包,一个份是业务代码,一份是打包的框架依赖。
weex 把weex-vue-framework 这类框架依赖内置到了SDK中,客户端访问Weex页面时,只会网络请求JS Bundle。由于JSFramework在本地,所以就减少了JS Bundle的体积,每个JS Bundle都可以减少一部分体积,从而提升了性能。
WXBridge 是 weex 实现的一种 js 和 客户端通信的机制。
js 执行环境和客户端是隔离的,为了和外界客户端的世界通信,需要有一个通信的桥梁。weex 实现了 WXBrigde, 主要通过 callJS 和 callNative 两个核心的方法,实现 js 代码和客户端代码双向通信。
在完成了上面的初始化之后,weex已经做好了准备,只等着下载 JS bundle 就可开始渲染页面了。
weex 能让一套代码能做成 native 级别的app,主要是做了三件事:
整体工作可以分为三个部分
1、转换 <template> 为 类JSON的树状数据结构, 转换数据绑定 为 返回数据的函数原型。#####
<foo a="{{x}}" b="1" /> --> {type: "foo", attr: {a: function () {return this.x}, b: 1}}.
2、转换 <style> 为 类JSON的树状数据结构。
.classname {name: value;} --> { classname : { name : value } }.
3、 把上面两部分的内容和 <script> 中的内容结合成一个JavaScript AMD(AMD:异步模块规范) 模块。#####
<template>
<foo a="{{x}}" b="1" class="bar"></foo>
</template>
<style>
.bar {width: 200; height: 200}
</style>
<script>
module.exports={
data: function () {
return {x: 100}
}
}
</script>
将转换为:
define('@weex-component/main', function () {
module.exports={
data: function () {
return {x: 100}
}
}
module.template={
type: "foo",
attr: {
a: function () {return this.x},
b: 1,
classname: ['bar']
}
}
module.style={
bar: {width: 200, height: 200}
}
})
bootstrap('@weex-component/main')
说明1:除此之外,转换器还会做一些额外的事情: 合并Bundle ,添加引导函数,配置外部数据等等。
说明2:案例来自Weex的官方文档。当前大部分Weex工具最终输出的JS Bundle格式都经过了Webpack的二次处理,所以你实际使用工具输出的JS Bundle会和上面的有所区别。
实际上当WEEX SDK获取到JS Bundle后,第一时间并不是立马渲染页面,而是先创建WEEX的实例。
每一个JS bundle对应一个实例,同时每一个实例都有一个instance id。
我们上文中说过,由于所有的js bundle都是放入到同一个JS执行引擎中执行,那么当js执行引擎通过WXBridge将相关渲染指令传出的时候,需要通过instance id才能知道该指定要传递给哪个weex实例
在创建实例完成后,接下来才是真正将js bundle交给js执行引擎执行。
在实例创建完成后,接下来就是执行JS bundle 了。JS bundle 的结果是生成Virtual DOM ,然后去patch 新旧 Vnode 树,根据diff 算法找出最佳的DOM操作,唯一和浏览器不同的是,调用的是 Native app api ,而不是浏览器里面对DOM节点增删改查的操作。
Weex 的渲染流程如下图:
Virtual DOM ->
-> Build Tree -> Apply Style -> Create View -> Update Frame -> Attach Event ->CSS Layout ->Update Frame
->Native/H5 View
输入:虚拟DOM
输出:Native UI 页面
参考文章:
Weex 2:浅说Weex工作原理 https://www.jianshu.com/p/32285c709682
深入理解weex内核原理 https://zhuanlan.zhihu.com/p/71064826
转载本站文章《Weex原理及架构剖析》,
请注明出处:https://www.zhoulujun.cn/html/webfront/AppDev/Weex/8495.html
文从内核角度切入,为大家带来Weex技术演进之路的分享。
随着Weex业务规模的扩大和业务覆盖场景的丰富,Weex 不仅在性能稳定性上面临越来越大的挑战,在安全隔离方面,也遇到前所未有的风险。
性能方面:例如,去年的“双11”和今年“双11”主会场规模对比,去年整个会场的JS Bundle大小控制在250K以内,今年主会场页面平均达到500K+,业务复杂度增加了接近2倍,Weex 的加载性能跟JS bundle 的大小基本成正相关;
稳定性方面:业务场景覆盖面的提升,从原来的偏展示的场景到偏交互场景的业务,以及一些常规业务的接入;新的业务场景,必然导致新的稳定性方面的挑战,事实也如此;
富交互:引入Gcanvas、AR/VR等富交互场景,对Weex js-native的通信效率要求极高;
安全性:旧引擎的安全漏洞的问题,以及业务之间存在相互污染,无法做到安全隔离的问题;
证书问题:Yoga引擎的证书授权问题;
从三个方面来阐述Weex 在内核重要方向的演进:JS引擎、Layout 引擎、WeexCore架构的演进;
JS引擎: 我们的目标是更快、更稳定、更安全、更小;其一:我们投入大量资源在JS引擎的优化上,从JS引擎的替换,由原来旧版本的V8 换成最新版本JavaScriptCore;其二:我们开创性地将JS Runtime 运行于独立的进程里,不仅保证主进程的稳定性,而且加入了智能恢复的能力;其三:重新考虑Weex 业务隔离的安全问题,开发设计了多Context 隔离的方案,保证避免业务间互相污染;其四:瘦身,包的精简;
Layout引擎:Weex项目成立以来,我们一直借用的Facebook的Yoga项目作为我们的布局引擎,但是Layout引擎对于Weex 项目又是如此重要,所以,我们今年10月份开始计划开发全新的Layout引擎开发的项目,来替换yoga引擎。第一,Layout 引擎作为核心模块,我们希望去主导演进的路线; 第二,Facebook的证书风险不能回避;所以我们决定重新开发自己的Layout 引擎,并争取做到更高性能,支持更多布局方式;
WeexCore架构:今年我们讨论最多的就是Weex 后续如何演进,在性能稳定性方面如何做的更优,在复杂业务的支持方面如何做的更好。WeexCore 首先是高性能的,用以满足更复杂场景业务开发,以及提升业务开发体验;其次是一个跨平台的内核,从DSL的跨平台到内核的跨平台。
JS引擎技术
众所周知,JS 引擎至于Weex至关重要,是Weex 最重要的一个核心模块,2017年,我们在JS 引擎的投入也是非常大:
2017-3月~2017-7月:对最新版本的V8和最新版本的JavaScriptCore 做来全面的profile,让profile数据告诉我们去选择哪个引擎作为Weex新一代的JS 引擎。经过4个月的努力,终于将最新版本的JavaScriptCore 在手机淘宝正式版本上线,同时Weex也是第一个将JavaScriptCore引擎(javascriptcore引擎apple维护的,很少在android平台商业化过)集成到手机淘宝这样体量的App中,中间遇到的兼容性的问题也是我们最大的挑战。最终性能提升还是比较明显的,手淘上Weex整体业务首屏加载时间提高了40%+,并全面支持ES6特性;
2017-7月~2017-10月:新版本的JavaScriptCore 上线以后,Weex的稳定性native crash 占比5%左右,按照手淘的稳定性要求(<1%)还是有比较大的差距,这个将是我们2017年双十一前最大的挑战。当时Weex稳定性小组的同学出于焦虑中,随着双十一临近,不断有新Weex 业务上线,伴随着冒出一些的兼容性的问题出来,始终看不到收敛的趋势。一方面,我们正向地去解决这些适配的问题,另一方面,我们也讨论如何彻底地解决JS引擎的稳定性的问题;后来,我们想到将JS 引擎独立运行到单独的进程里去,这个方案带来最大的好处,就是Weex 业务的crash 不会影响主程序的稳定性;这个方案也成了双十一Weex稳定性保障的救命稻草。最终这个方案在10月份前正式上线,效果非常明显,Weex 引起的native crash占比一下子从5%下降到0.5%左右。
2017~11月~至今:双十一之后,JS 引擎项目主要在做两个事情,一个Weex安全隔离方案,另一个是包精简优化方案;Weex安全隔离方案主要解决页面隔离的问题,双十一当天也遇到一个非常严重的全局污染的案例,某个业务不小心污染了全局对象,导致所有的Rax的页面出现白屏的问题;针对这些案例,我们重新设计了Weex 安全隔离的方案,目前安全隔离方案已经内部灰度中,预计2月份正式社区发布;
包精简优化方案:主要解决Weex sdk集成了最新版本的JavaScriptCore以后,包大小增大一倍的问题(4.2M左右),包的增大直接增大了App接入的门槛,特别是对包大小非常敏感的App。目前同步一下信息:精简优化方案目前也基本开发完毕,预计可以减少到2.6M左右,预计也是2月份上线;
独立进程化
问题
同一个进程中,与主App存在资源竞争,尤其是内存问题比较突出,JavaScriptCore虽然执行性能提升了,但对内存的消耗也同时增大不少,所以替换成JSC以后,Weex的内存问题导致Crash也明显上升;
独立进程的方案本身比较Hack,再加上Android生态的碎片化,开发过程中也遇到很多适配问题,比如在某些机型上独立进程拉不起来,导致业务渲染失败;
JavaScriptCoe引擎本身对android平台适配比较差,没有比较大体量的App在线上应用过;
优势
进程独立以后,完全和主App的进程隔离,避免了进程资源竞争导致crash的问题,Weex的crash也不会引起主进程的crash;
Weex 原有的三个线程架构,JS 线程任务被并行成两个,JS独立的进程和原来JS线程,整体增强了JS任务执行的并发性,抵消了方案本身的IPC通信的性能损耗;
独立进程后,我们加入了自修复的能力,增强了JS Runtime进程的自动重置功能,解决JS Runtime 异常后的无法自动恢复的问题,极大地保障业务的稳定性;
SandBox机制
Weex 原有的设计,所有Weex页面包括JSFrameWork 都是运行在同一个JS Context里,并在JS层面,对全局的JS 变量做了freeze操作,防止被其他业务页面污染。这个设计主要还是出于高性能和安全性的综合考量。
2017年双十一出现的全局污染的问题,让我们重新思考Weex Context的安全隔离的方案,安全稳定高于一切。经过新的讨论后,我们决定针对每个Weex页面都创建一个JS Context 作为独立的运行环境,页面依赖的全局对象由Global Contex统一生层并传递给每个页面的Contex;传输的过程,我们做了两个非常重要的操作:
1)对传输的对象做freeze操作;
2)在javaScript引擎层面,通过native的SetPrototype接口切断原型链的关系;这样就彻底解决了页面间互相污染的问题。该方案预计2月份正式上线。
Layout 引擎
全新的Layout引擎参考了 Google的FlexLayout的算法流程,重新实现了Weex的 Flex布局,目前性能和功能方面基本和yoga保持一致,后续会做一些性能优化。至于未来如何演进,团队同学讨论几个关键的步骤:
自主开发全新的高性能的跨平台Layout引擎,统一由C++实现,IOS/android 两端复用同一套代码;
扩展更多的布局方式,比如Gird布局、Absolute布局等
编译器或服务端做预布局,提升端测的布局效率等;
该方案预计2月份正式上线。
Weex 作为一个跨平台的开发框架,在Android/ IOS/HTML 三端实现跨平台一致性非常重要。目前Weex 核心渲染流程分平台实现,不仅多人维护导致不可避免的逻辑实现差异,而且对于后续新平台扩展成本也非常高(核心渲染流程需要重新实现)。因此,想到抽象统一Weex 核心解析渲染流程,通过C + + 语言实现,实现 ios、android 平台核心逻辑统一,不仅可以增强平台间的一致性,降低维护成本,以及扩展平台的成本。通过C+ +代码执行效率要高于JAVA,同时还可提高Android端的代码执行性能。
提供标准的Weex Dom API Layer,简化DSL的接入成本,将大部分JSFramework native化;
抽象Weex平台无关的、核心的处理逻辑,android和IOS的porting层尽量做薄,一方面提高代码的复用率,另一方面降低新平台的扩展成本;
架构设计上的高可用,通用的模块可插拔,例如JS engine 模块和Layout engine模块能低成本地切换;
核心技术模块比如JS engine 等能标准化输出,服务更多的业务场景;
(本文作者饮源,阿里巴巴技术专家)
*请认真填写需求信息,我们会在24小时内与您取得联系。