UNI-APP底层原理

0 阅读4分钟

与微信小程序类似,UNI-APP的核心底层原理也是双线程架构,但它更进一步,是一个更宏大、更完整的“编译器 + 运行时”双引擎架构-1-5。它通过编译时的转换和运行时的适配,将一套代码发布到iOS、Android、H5、以及各类小程序平台。

下面这个流程图可以帮你更直观地理解UNI-APP是如何将一套代码分发到不同平台的:

image.png

这个流程可以分解为两大核心部分:

🏗️ 编译器:多端代码的转换器

这是UNI-APP实现跨端的起点,它运行在开发环境中,负责将你的.vue 文件翻译成各平台能懂的语言-1

  • 编译过程:编译器会解析你的Vue模板、JS和CSS,生成抽象语法树(AST),然后通过一系列插件进行平台适配改造,最后输出目标代码-5

  • 输出示例

    • 编译到 Web平台,它会生成标准的HTML、CSS和JS文件-1-5
    • 编译到微信小程序,它会将.vue 文件拆分成.wxml.wxss.js.json 文件-1-6
    • 编译到 App平台,对于普通的.vue 页面,会生成JS代码;对于.nvue 页面或涉及.uts 文件的部分,则会编译为原生的Kotlin(Android)或Swift(iOS)代码-1
  • 关键工具:编译器支持条件编译,让你可以通过特殊的注释,为不同平台编写专属代码-1-5。UNI-APP也提供了基于Webpack(Vue2版)和Vite(Vue3版)两套编译体系-1-5

🚀 运行时:跨端能力的执行者

当代码编译完成后,就需要在各自平台的运行时环境中执行。这个运行时主要负责解析编译后的代码,并提供跨端的API和组件。

  • 逻辑层与视图层分离(非H5端) :这是UNI-APP性能的核心。它效仿了小程序的架构,将JS业务逻辑和页面渲染拆分开来-2-7-10

    • 逻辑层:运行在一个独立的JS引擎(iOS是JSCore,Android是V8)中,负责处理数据、事件和API调用。它不依赖WebView,因此没有浏览器兼容问题,但不能使用windowdocument等浏览器专有API-2-7-10
    • 视图层:负责页面的渲染。对于.vue 页面,它仍然是WebView;而对于.nvue 页面,则使用基于Weex改进的原生渲染引擎-1-2-7
  • 通信桥梁(JSBridge) :逻辑层和视图层分离后,它们之间的通信就需要一个桥梁。UNI-APP通过内置的桥接层,让两端可以通过统一的JSON格式消息进行通信-3。开发者可以使用uni.requireNativePlugin调用原生模块,或通过事件监听(uni.onNativeEventReceive)接收原生层发送的数据-3

  • 跨端API适配:你在代码中写的uni.requestuni.getStorage等API,在运行时会被动态地映射为对应平台的实现。例如,在微信小程序中,uni.request底层调用的就是wx.request-1

⚠️ 通信的代价与优化

逻辑层和视图层分离虽好,但也带来了通信损耗。特别是在Android低端机上,每次通信可能耗时几十毫秒-2-7。这在连续高帧率的Canvas动画或需要频繁反馈的拖拽交互中,会造成卡顿-2-7

为了应对这个挑战,UNI-APP提供了几种“开挂”方案:

  • renderjs (for App-vue & H5) :一个运行在视图层的JS。它可以直接操作视图层的DOM,处理像Canvas动画这类频繁交互的任务,完全绕开了跨层通信,实现丝滑流畅-2-7
  • wxs (for 微信小程序) :微信小程序提供的类似方案,UNI-APP也支持将其编译到微信小程序、App和H5中-2
  • bindingx (for App-nvue) :在原生渲染的nvue中,通过bindingx可以一次性将一个动画表达式传递给原生层,由原生层解析并执行,避免反复通信-2-7

总结来说,UNI-APP的底层原理就像一个精心设计的“翻译官”和“包工头”的组合:编译时,它化身“翻译官”,将你的Vue代码翻译成各平台的本地方言;运行时,它又化身“包工头”,在幕后搭建起逻辑与渲染的双线程架构,并通过JSBridge进行调度,同时准备好各种“秘密武器”(如renderjs)来解决通信带来的性能问题。

与微信小程序专注于单一平台内的双线程通信相比,UNI-APP的架构更像是一个更宏观的跨端调度系统。它的编译器负责将一套代码转化为不同平台(包括小程序、App、H5)的本地化语言,而在App和小程序端内部,则沿用了类似的双线程模型来保证性能