用WEB技术栈开发NATIVE应用(二):WEEX 前端SDK原理详解

简介: WEEX依旧采取传统的web开发技术栈进行开发,同时app在终端的运行体验不输native app。其同时解决了开发效率、发版速度以及用户体验三个核心问题。那么WEEX是如何实现的?目前WEEX已经完全开源,并捐给Apache基金会,我们可以通过分析其源码来一探究竟。

作者:阿里-移动云-大前端团队

传统的移动端开发,一个完整的业务需要维护三份终端代码:Android、iOS、H5,这带来了极大的开发成本以及维护成本。尤其是对处于业务初创期需要快速试错的业务以及需要支持定期运营活动的业务。所以业界也一直在探索跨平台方案,旨在通过一套代码完成各个终端的业务逻辑。相关方案经过不断演化,从早期的H5、Hybrid到如今的Cloud Native(云原生),在开发效率和用户体验上都在一点点逼近最初的设想。

早期H5和Hybrid方案的核心是利用终端的内置浏览器(webview)功能,通过开发web应用满足跨平台需求。该方案可以解决跨平台问题,同时可以提升发版效率。但其最大的弊端在于用户体验相较于native开发的app存在较大差距,经常出现页面卡顿,加载慢等问题。

于是后来业界开始探索依旧利用web技术栈开发出媲美原生体验app的方案,于是以WEEX为代表云原生开发框架开始出现。所谓云原生(Cloud Native)指可以通过云端快速发布(与远程web应用发布流程类似),同时还可以达到媲美原生App体验的方案。WEEX依旧采取传统的web开发技术栈进行开发,同时app在终端的运行体验不输native app。其同时解决了开发效率、发版速度以及用户体验三个核心问题。那么WEEX是如何实现的?目前WEEX已经完全开源,并捐给Apache基金会,我们可以通过分析其源码来一探究竟。

WEEX框架主要分为两部分:

  • 前端JavaScript框架
  • Native SDK

在上一篇博客中,我们介绍了Native SDK的原理,本文主要介绍其前端JavaScript框架原理。

1 整体架构

首先还是再来看下WEEX开发的整体架构:

weex1

可以看到在JS-Native Bridge将渲染指令发送给Android或者iOS渲染引擎之前,我们的业务代码运行在JSCore/v8的执行引擎之中,而在该执行引擎之中除了执行业务JSBundle,还运行着JS FrameworkJS Framework不仅提供了jsbundle必要的运行时环境,同时还提供了与native通信的接口。

而这个JS Framework就是我们今天介绍的重点。

weex11

这是前端框架的主要架构:

  • FRONTEND FRAMEWORK/DSL:这是WEEX的开发框架,目前WEEX主要是使用Vue.js进行开发
  • WEEX-VUE-LOADER:前端编译器,将vue文件编译成es5代码
  • WEEX-VUE-FRAMWORK:WEEX核心框架,主要负责将virtual dom转换成weex的native dom api
  • WEEX-RUNTIME:负责与native渲染引擎对接,将native dom api转换成对应平台(Android、iOS)的platform api,然后传递给native渲染引擎,由后者负责渲染工作。

2 Vue.js

首先来看下前端开发框架Vue.js,Vue.js目前与ReactAngular构成了三大最流行的前端开发框架,Vue.js具有组件化、virtual dom以及MVVM三大特性,还学习ReactRedux,引入了状态管理模块Vuex。同时相比起React主要基于JSXVue.js的开发模式更加清晰,简单,上手速度更快。.vue 文件通常可以分为三部分:<template><style><script><template> 是必须要有的,其他可选。其中 <script>中的代码会保留或者被转换成 ES5 的语法;<style> 中的 CSS 在 Weex 平台上会被转换成 JSON 格式的样式声明,放到组件的定义中去;<template> 会被编译生成组件定义中 render 函数,可以理解为 render 函数的语法糖。下文是一个简单的.vue文件:

<template>
  <div style="justify-content:center;">
    <text class="freestyle">Hello World!</text>
  </div>
</template>

<style scoped>
  .freestyle {
    text-align: center;
    font-size: 200px;
  }
</style>

3 WEEX-VUE-LOADER

由于.vue文件并不是标准的JavaScript代码,该代码不能直接被JS执行引擎识别,所以在编译过程中需要将.vue文件转化成标准的es5代码。而负责完成这一操作的就是WEEX-VUE-LOADER

4 WEEX-VUE-FRAMEWORK&WEEX-RUNTIME

完成编译后,输出的bundle.js即可被JS执行引擎所识别,可以执行其逻辑了。那么接下来就来看下bundle.js的执行过程。

4.1 初始化

首先来看下初始化过程。

weex12

图中画出了 Weex SDK 的部分内容。其中 weex-vue-frameworkVue.js 是对等的,语法和内部机制都是一样的,只不过 Vue.js最终创建的是 DOM 元素,而 weex-vue-framework 则是向原生端发送渲染指令,最终渲染生成的是原生组件。Weex Runtime 用来对接上层前端框架( Vue.js )并且负责和原生端之间的通信。Render Engine 就是针对各个端开发的原生渲染器,包含了 Weex 内置组件和模块的实现,可扩展。

4.2 创建组件

weex接收到bundle.js之后,首先检查其合法性,如果发现用的是Vue版本(weex早期版本使用.we语法),就会调用weex-vue-framework中提供的createInstance创建实例。一个bundle.js对应一个weex实例,且每一个实例都有唯一的instanceId,与之对应。实例与实例之间相互隔离,互不干扰。

在创建实例的过程中,bundle.js会执行new Vue()创建一个vue组件,并通过其render函数创建VNode节点,即virtual dom节点。第二节中的示例代码会最终生成类似如下的vnode节点:

{
  tag: 'div',
  data: {
    staticStyle: { justifyContent: 'center' }
  },
  children: [{
    tag: 'text',
    data: {
      staticClass: 'freestyle'
    },
    context: {
      $options: {
        style: {
          freestyle: {
            textAlign: 'center',
            fontSize: 200
          }
        }
      }
    },
    children: [{
      tag: '',
      text: 'Hello World!'
    }]
  }]
}

4.3 patch

生成了VNode之后,接下来需要将VNode同步到真实的Dom之上,该过程在Vue.js中被称为patchpatch会比较新旧VNode之间的差异,最小化操作集。最后再将Virual Dom整体更新到真实Dom之上。在执行 patch 之前的过程都是 Web 和 Weex 通用的,所以文件格式、打包编译过程、模板指令、组件的生命周期、数据绑定等上层语法都是一致的。

然而由于目标执行环境不同(浏览器和 Weex 容器),在渲染真实 UI 的时候调用的接口也不同。

weex13

vue.js内部,weex平台和web平台的patch方法有所不同。简单来讲,在web平台,patch需要将Virtual Dom利用标准Dom API更新到真实Dom即可。接下来的UI更新就交给浏览器即可。

但是由于在weex平台下,最终的UI渲染是由native渲染引擎执行的,native渲染引擎不能识别Dom API,所以在weex平台下,需要将Virtual DOM转化成native 渲染引擎可以识别的Native DOM API

4.3 发送渲染指令

在上层前端框架调用了 Weex 平台提供的 Native DOM API 之后,Weex Runtime 会构建一个用于渲染的节点树,并将操作转换成渲染指令发送给客户端。

回顾文中提到的 例子,上层框架调用了 Weex Runtime 中 createBodycreateElementappendChild 这三个接口,简单构建了一个用于渲染的节点树,最终生成了两条渲染指令。

weex14

Platform API 指的是原生环境提供的 API,这些 API 是 Weex SDK 中原生模块提供的,不是 js 中方法,也不是浏览器中的接口,是 Weex 内部不同模块之间的约定。

目前来说渲染指令是基于 JSON 描述的,具体格式大致如下所示:

{
  module: 'dom',
  method: 'createBody',
  args: [{
    ref: '_root',
    type: 'div',
    style: { justifyContent: 'center' }
  }]
}
{
  module: 'dom',
  method: 'addElement',
  args: ['_root', {
    ref: '2',
    type: 'text',
    attr: { value: 'Hello World!' },
    style: { textAlign: 'center', fontSize: 200 }
  }]
}

4.4 渲染原生组件

接下来就是WEEX NATIVE SDK的工作了,具体逻辑在上一篇博客已经详细说明了,此处仅简单说明。

原生渲染器接收上层传来的渲染指令,并且逐步将其渲染成原生组件。

渲染指令分很多类,文章中提到的两个都是用来创建节点的,其他还有 moveElementupdateAttrsaddEvent 等各种指令。原生渲染器先是解析渲染指令的描述,然后分发给不同的模块。关于 UI 绘制的指令都属于 "dom" 模块中,在 SDK 内部有组件的实现,其他还有一些无界面的功能模块,如 stream 、navigator 等模块,也可以通过发送指令的方式调用。

这个例子里,第一个 createBody 的指令就创建了一个 <div> 的原生组件,同时也将样式应用到了改组件上。第二个 addElement指令向 <div> 中添加一个 <text> 组件,同时也声明了组件的样式和属性值。

上述过程不是分阶段一个一个执行的,而是可以实现“流式”渲染的,有可能第一个 <div> 的原生组件还没渲染好,<text> 的渲染指令又发过来了。当一个页面特别大时,能看到一块一块的内容逐渐渲染出来的过程。

5 总结

通过本文以及上一篇:WEEX NATIVE SDK原理详解,总算是将weex的大致原理介绍清楚了,当然还有很多实现细节文中并未展开,有兴趣的朋友可以留言大家一起讨论下,另外文章中有错误的地方也请大家指正!

相关文章
|
17天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
75 3
|
21天前
|
前端开发 JavaScript 测试技术
前端工程化:构建高效、可维护的现代Web应用
【10月更文挑战第5天】前端工程化:构建高效、可维护的现代Web应用
|
21天前
|
前端开发 测试技术 持续交付
前端工程化:构建高效、可维护的现代Web应用
【10月更文挑战第5天】前端工程化:构建高效、可维护的现代Web应用
|
27天前
|
缓存 前端开发 JavaScript
前端技术探索:构建高效、响应式Web应用的秘诀
前端技术探索:构建高效、响应式Web应用的秘诀
48 0
|
19天前
|
负载均衡 前端开发 JavaScript
前端研发链路之开发
本文首发于微信公众号“前端徐徐”,作者徐徐。文章介绍了前端研发链路中的开发部分,重点探讨了开发服务器(dev-server)、热更新(hot-reload)、数据模拟(mock)和代理(proxy)等关键技术,帮助开发者理解其基本原理和应用场景,提升开发效率和代码质量。
32 2
前端研发链路之开发
|
26天前
|
前端开发 JavaScript 关系型数据库
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
这篇文章介绍了一个名为Vue3Admin的全栈后台应用,前端基于SoybeanAdmin二次开发,后端基于Nest.js。主要使用了Vue3.5、AntDesignVue、UnoCSS、Pinia等前端技术栈,以及Nest.js、PostgreSQL、Prisma等后端技术栈。文章详细描述了系统的功能设计,包括动态国际化语言配置、登录用户操作日志、用户和角色权限映射、动态路由菜单、消息公告发布及前端业务功能等。同时,也提供了项目运行所需的环境和依赖,以及如何拉取代码、安装依赖和启动项目的方法。最后,文章展示了项目的演示图,并对项目进行了总结,指出项目未经严格测试,仅供学习交流使用。
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
|
13天前
|
人工智能 前端开发 测试技术
探索前端与 AI 的结合:如何用 GPT-4 助力开发效率
本文介绍了 GPT-4 如何成为前端开发者的“神队友”,让开发变得更加高效愉快。无论是需求到代码的自动生成、快速调试和性能优化,还是自动化测试和技术选型,GPT-4 都能提供极大的帮助。通过智能生成代码、捕捉 BUG、优化性能、自动化测试生成以及技术支持,GPT-4 成为开发者不可或缺的工具,帮助他们从繁重的手动任务中解脱出来,专注于创新和创意。GPT-4 正在彻底改变开发流程,让开发者从“辛苦码农”转变为“效率王者”。
24 0
探索前端与 AI 的结合:如何用 GPT-4 助力开发效率
|
23天前
|
设计模式 测试技术 持续交付
开发复杂Web应用程序
【10月更文挑战第3天】开发复杂Web应用程序
30 2
|
1天前
|
监控 前端开发 JavaScript
前端技术探索:构建高效、可维护的Web应用
【10月更文挑战第23天】前端技术探索:构建高效、可维护的Web应用
5 0
|
1天前
|
JavaScript 前端开发 Java
SpringBoot_web开发-webjars&静态资源映射规则
https://www.91chuli.com/ 举例:jquery前端框架
8 0