写点什么

Weex 原理及架构剖析

作者:zhoulujun
  • 2023-04-09
    广东
  • 本文字数:2798 字

    阅读完需:约 9 分钟

早期 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框架架构图


WEEX SDK JavaScript 执行架构图


React Native 架构


React 可以渲染到多平台上


Weex 架构分析

js 的执行环境

在初始化阶段, WEEX SDK 会准备好一个 js 的执行环境。因为我们是要在客户端跑 js 代码的,所以需要一个 js 执行环境,这个执行环境类似于浏览器的 v8 引擎, 在 IOS 上,则是客户端自带的 js core。

这个 js 执行环境,可以看成是一个在客户端上的沙盒,或者是一个虚拟机

为了提升性能,js 执行环境只用在初始化的时候初始化一次,之后每个页面都无须再初始化了。也就是说不管客户端打开多少个 weex 页面,多个页面的 JS 都是跑在同一个 js 执行环境中的

weex-vue-famework 框架

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 通信

WXBridge 是 weex 实现的一种 js 和 客户端通信的机制

js 执行环境和客户端是隔离的,为了和外界客户端的世界通信,需要有一个通信的桥梁。weex 实现了 WXBrigde, 主要通过 callJS 和 callNative 两个核心的方法,实现 js 代码和客户端代码双向通信。

在完成了上面的初始化之后,weex 已经做好了准备,只等着下载 JS bundle 就可开始渲染页面了。

Weex 工作原理分析

weex 能让一套代码能做成 native 级别的 app,主要是做了三件事:

  • 在本地用一个叫做 transformer 的工具把这套代码转成纯 JavaScript 代码

  • 在客户端运行一个 JavaScript 引擎,随时接收 JavaScript 代码

  • 在客户端设计一套 JS Bridge,让 native 代码可以和 JavaScript 引擎相互通信


weex跨端原理 编译分析


整个 Weex 的工作原理


Weex 源码转换成 JS Bundle

整体工作可以分为三个部分

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 会和上面的有所区别。

获取到 JS Bundle 后创建 weex 实例

实际上当 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 节点增删改查的操作。


Native 渲染

Native 渲染引擎提供客户端组件(Component)和模块(Module)

  • 组件(Component):在屏幕内可见,有特定行为,能被配置不同的属性和样式,能响应用户交互,常见的组件有: <div>、<text>、 <image>。

  • 模块(Module): 是一组能被 JS Framework 调用的 API. 其中的一些能以异步的方式调用 JS Framework, 例如: 发送 HTTP 请求。

Weex 的渲染流程

Weex 的渲染流程如下图:

Virtual DOM ->

->    Build Tree -> Apply Style -> Create View -> Update Frame ->  Attach Event ->CSS Layout ->Update Frame

->Native/H5 View

输入:虚拟 DOM

  1. 构造树结构. 分析虚拟 DOM JSON 数据以构造渲染树(RT).

  2. 添加样式. 为渲染树的各个节点添加样式.

  3. 创建视图. 为渲染树各个节点创建 Native 视图.

  4. 绑定事件. 为 Native 视图绑定事件.

  5. CSS 布局. 使用 css-layout 来计算各个视图的布局.

  6. 更新视窗(Frame). 采用上一步的计算结果来更新视窗中各个视图的最终布局位置.

输出: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

用户头像

zhoulujun

关注

还未添加个人签名 2021-06-25 加入

15年草根站长,尽在:zhoulujun.cn

评论

发布
暂无评论
Weex原理及架构剖析_Weex_zhoulujun_InfoQ写作社区