关于前端:Mpx28-版本正式发布使用组合式-API-开发小程序

2次阅读

共计 12153 个字符,预计需要花费 31 分钟才能阅读完成。

作者:hiyuki

小程序跨端开发框架 Mpx 自 18 年立项开源以来,现在曾经走过了第四个年头,其高性能、优体验、跨平台的个性播种了公司内外开发者用户的统一好评。

为了不辜负开发者用户对咱们的信赖,更好地反对团体小程序业务开发,一方面咱们对 Mpx 的稳固版本进行着高频的保护迭代,疾速响应解决团体内外开发者用户在框架开发应用过程中遇到的问题;另一方面咱们继续跟进摸索业内最新动静,力争将更新更好的开发能力与体验带给小程序开发者用户。继年初咱们在 2.7 版本中对 Mpx 的编译系统进行重构适配 Webpack5,基于长久化缓存大幅晋升编译速度后,在最新的 2.8 版本中,咱们对 Mpx 的运行时框架也进行了大量重构革新工作,残缺反对了 Vue3 提出的组合式 API 开发范式,让用户可能应用当下最热门的开发方式进行小程序开发,咱们先来简略感受一下组合式 API 的应用:

<template>
  <view>{{collectionName}}: {{book.title}}({{readersNumber}})</view>
  <button bindtap="addReaders">addReaders</button>
</template>

<script>
  import {createComponent, ref, reactive, onMounted} from '@mpxjs/core'

  createComponent({
    properties: {collectionName: String},
    setup () {const readersNumber = ref(0)
      const book = reactive({title: 'Mpx'})

      onMounted(() => {console.log('Component mounted.')
      })

      // 裸露给 template
      return {
        readersNumber,
        book,
        addReaders () {readersNumber.value++}
      }
    }
  })
</script>

能够看出和 Vue3 组合式 API 的应用是高度相似的,利用框架导出的一系列响应式 API 和 生命周期钩子函数在 setup 中编写业务逻辑,并将模板依赖的数据与办法作为返回值返回,与传统的选项式 API 相比,组合式 API 具备以下劣势:

  • 更好的逻辑复用,通过函数包装复用逻辑,显式引入调用,不便简洁且合乎直觉,躲避打消了 mixins 复用中存在的缺点;
  • 更灵便的代码组织,相比于选项式 API 提前规定了代码的组织形式,组合式 API 在这方面简直没有做任何限度与规定,更加灵便自在,在性能简单的宏大组件中,咱们可能通过组合式 API 让咱们的性能代码更加内聚且有条理,不过这也会对开发者本身的代码标准意识提出更高要求;
  • 更好的类型推导,尽管基于 this 的选项式 API 通过 ThisType 类型体操的形式也能在肯定水平上实现 TS 类型推导,但推导和实现老本较高,同时依然无奈完满笼罩一些简单场景(如嵌套 mixins 等);而组合式 API 以本地变量和函数为根底,自身就是类型敌对的,咱们在类型方面简直不须要做什么额定的工作就能享受到完满的类型推导。

同时与 React Hooks 相比,组合式 API 中的 setup 函数只在初始化时单次执行,在数据响应能力的加持下大大降低了了解与应用老本,基于以上起因,咱们决定为 Mpx 增加组合式 API 能力,让用户可能用组合式 API 形式进行小程序开发。

组合式 API 实现

从下面的简略示例中能够看出,抛开响应式 API 和生命周期注册模式的变动,组合式 API 的实现要点在于动静增加模板依赖的数据和办法,这也是咱们在小程序中实现组合式 API 可能遇到的核心技术卡点。

对于动静增加模板依赖数据,咱们在过来的实际中曾经充分证明了其可行性,事实上,从 Mpx 最后的版本开始,咱们就充分利用了这项能力来实现咱们对计算属性和 dataFn(相似于 Vue 应用函数定义 data)的反对,这项能力的关键在于存在适合的生命周期用于动静增加初始化数据,这里对于初始化数据的定义是可能影响组件树的初始渲染,举个简略的例子:存在一对父子组件 parent/child,parent 应用 props 向 child 传递数据,当咱们在 parent 初始创立时应用 setData 动静增加 props 数据,同时 child 在初始创立时可能通过 props 正确获取到这部分的数据时,咱们就能够将这部分动静增加的数据视作初始化数据,这是咱们在小程序中实现齐备数据响应反对的根底。

侥幸的是,目前业内所有支流小程序平台(微信 / 支付宝 / 百度 / 字节 /QQ)都反对了上述能力,微信从一开始就反对在 attached 生命周期中调用 setData 函数动静增加初始化数据,在上述的父子 props 传递场景中,也可能在子组件的 attached 中正确获取这部分数据,支付宝和字节小程序一开始并不反对该能力,不过支付宝在 component2 组件零碎重构后,字节在橙心合作项目中与咱们沟通后,都胜利反对了该能力。

而对于动静返回的办法,最简略能想到的计划就是间接挂载到组件实例上,通过咱们的残缺测试,上述业内支流小程序平台都反对应用这种形式动静增加办法,基于以上事实,咱们十分确定组合式 API 可能在小程序环境中顺利实现,下图简要展现了 Mpx 反对组合式 API 的初始化流程:

生命周期钩子函数

在组合式 API 中,setup 函数只有在组件创立时初始化单次执行,因而须要提供一系列生命周期钩子函数来代替选项式 API 中的生命周期钩子选项,因为小程序原生只反对选项式的生命周期注册形式,咱们通过 预注册 -> 驱动 的形式来实现 setup 中函数式注册生命周期钩子的语法糖,简略来讲就是应用选项式 mixins 的形式提前注册所有须要的生命周期钩子,在选项式生命周期钩子执行时驱动对应在 setup 中应用生命周期钩子函数注册的代码逻辑执行,如下图所示:

作为跨端小程序框架,Mpx 须要兼容不同小程序平台不同的生命周期,在选项式 API 中,咱们在框架中内置了一套对立的生命周期,将不同小程序平台的生命周期转换映射为内置生命周期后再进行对立的驱动,以抹平不同小程序平台生命周期钩子的差别,如微信小程序的 attached 钩子和支付宝小程序的 onInit 钩子,在组合式 API 中,咱们沿用了同样的逻辑,设计了一套与框架内置生命周期对应的生命周期钩子函数,以雷同的形式进行驱动,因而这些生命周期钩子函数人造具备了跨平台个性,下表显示了在组件 / 页面中框架生命周期与原生平台生命周期的对应关系:

框架内置生命周期 Hooks in setup 微信原生 支付宝原生
BEFORECREATE null attached(数据响应初始化前) onInit(数据响应初始化前)
CREATED null attached(数据响应初始化后) onInit(数据响应初始化后)
BEFOREMOUNT onBeforeMount ready(MOUNTED 执行前) didMount(MOUNTED 执行前)
MOUNTED onMounted ready(BEFOREMOUNT 执行后) didMount(BEFOREMOUNT 执行后)
BEFOREUPDATE onBeforeUpdate nullsetData 执行前) nullsetData 执行前)
UPDATED onUpdated nullsetData callback) nullsetData callback)
BEFOREUNMOUNT onBeforeUnmount detached(数据响应销毁前) didUnmount(数据响应销毁前)
UNMOUNTED onUnmounted detached(数据响应销毁后) didUnmount(数据响应销毁后)
ONLOAD onLoad onLoad onLoad
ONSHOW onShow onShow onShow
ONHIDE onHide onHide onHide
ONRESIZE onResize onResize events.onResize

同 Vue3 一样,Mpx 在组合式 API 中没有提供 BEFORECREATECREATED 对应的生命周期钩子函数,用户能够间接在 setup 中编写相干逻辑。

具备副作用的页面事件

在小程序中,一些页面事件的注册存在副作用,即该页面事件注册与否会产生实质性的影响,比方微信中的 onShareAppMessageonPageScroll,前者在不注册时会禁用以后页面的分享性能,而后者在注册时会带来视图与逻辑层之间的线程通信开销,对于这部分页面事件,咱们无奈通过 预注册 -> 驱动 形式提供组合式 API 的注册形式,用户能够通过选项式 API 的形式来注册应用,通过 this 拜访组合式 API setup 函数的返回。

然而这种应用形式显然不够优雅,咱们思考是否能够通过一些非常规的形式提供这类副作用页面事件的组合式 API 注册反对,例如,借助编译伎俩。咱们在运行时提供了副作用页面事件的注册函数,并在编译时通过 babel 插件的形式解析辨认到以后页面中存在这些非凡注册函数的调用时,通过框架已有的 编译 -> 运行时注入 的形式将事件驱动逻辑增加到以后页面当中,以提供绝对优雅的副作用页面事件在组合式 API 中的注册形式,同时不产生非预期的副作用影响,简略示例如下:

import {createPage, ref, onShareAppMessage} from '@mpxjs/core'

createPage({setup () {const count = ref(0)

    onShareAppMessage(() => {
      return {title: '页面分享'}
    })

    return {count}
  }
})

目前咱们通过这种形式反对的页面事件如下:

页面事件 Hooks in setup 平台反对
onPullDownRefresh onPullDownRefresh 全小程序平台 + web
onReachBottom onReachBottom 全小程序平台 + web
onPageScroll onPageScroll 全小程序平台 + web
onShareAppMessage onShareAppMessage 全小程序平台
onTabItemTap onTabItemTap 微信 / 支付宝 / 百度 /QQ
onAddToFavorites onAddToFavorites 微信 / QQ
onShareTimeline onShareTimeline 微信
onSaveExitState onSaveExitState 微信

特地留神,因为动态编译剖析实现形式的限度,这类页面事件的组合式 API 应用须要满足页面事件注册函数(如onShareAppMessage)的调用和 createPage 的调用位于同一个 js 文件当中。

对于生命周期钩子函数的更多信息能够查看这里。

<script setup>

同 Vue3 一样,咱们在 .mpx 单文件组件 / 页面中实现了 <script setup> 的组合式 API 编译语法糖,相较于惯例的写法,<script setup> 具备以下劣势:

  • 更少的样板内容,更简洁的代码
  • 可能应用纯 TypeScript 申明 props 类型
  • 更好的 IDE 类型推导性能

简略应用示例如下:

<script setup>
  import {ref} from '@mpxjs/core'

  const msg = ref('hello')

  function log () {console.log(msg.value)
  }
</script>
<template>
  <view>msg: {{msg}}</view>
  <view ontap="log">click</view>
</template>

能够看到应用形式与 Vue3 基本一致,不过因为 Mpx 的组合式 API 设计实现与 Vue3 存在差别,对应 <script setup> 也与 Vue3 中存在一些差别:

  • 不反对 import 快捷注册组件
  • 没有 defineEmits() 编译宏
  • 没有 useSlots()useAttrs() 运行时函数
  • 以编译宏的模式提供了 useContext(),获取 setup 函数的第二个参数 context
  • defineExpose() 编译宏的作用与 Vue3 中有所差异,可能限定模板中能拜访的变量范畴

特地留神,受小程序底层技术限度,咱们在 Mpx 的实现中无奈像 Vue3 那样将模板编译的渲染函数和 <script setup> 搁置到同一作用域下进行变量拜访,而是通过动态编译剖析提取出 <script setup> 的顶层作用域变量,再以上文中提到的动静增加数据与办法的形式将其设置到模板当中,如果 <script setup> 中申明了较多顶层作用域变量,它们并不一定都会被模板拜访,就会带来有效的性能开销,因而咱们强烈建议应用 defineExpose() 限定模板中能拜访的变量范畴,你能够把它等同于 setup 函数中的 return

对于 <script setup> 的更多信息能够查看这里。

组合式 API 与 Vue3 中的差别

咱们来总结一下 Mpx 中组合式 API 与 Vue3 中的区别:

  • setupcontext 参数不同,详见这里
  • setup 不反对返回 渲染函数
  • setup 不能是异步函数
  • <script setup> 提供的宏办法不同,详见这里
  • <script setup> 不反对 import 快捷注册组件
  • 反对的生命周期钩子不同,详见这里
  • 模板援用的形式不同,详见这里

对于组合式 API 的更多信息能够查看这里。

响应式 API 实现

组合式 API 的失常工作离不开响应式 API 的反对,上面咱们来聊聊 Mpx 中响应式 API 的设计实现。咱们晓得 Vue3 中响应式 API 基于 proxy 进行了重构实现,然而目前 proxy 的浏览器兼容占比依然无奈达到咱们对于线上可用性的要求,因而在 Mpx 中,咱们依然基于 Object.defineProperty 进行外围数据响应能力的实现,同时借鉴了 Vue3 中优良的代码设计与实现,如 reactiveEffecteffectScope 等,尽可能实现与 Vue3 中响应式 API 能力对齐。

说到这里,很多同学可能会想到 @vue/composition-api 这个库,该库提供的要害能力正是基于 Vue2 的数据响应系统模拟实现 Vue3 中的响应式 API,咱们在后期也对 @vue/composition-api 在 Mpx 中的复用进行了十分有价值的摸索尝试。不过最终咱们还是决定在 Mpx 的运行时框架中进行独立实现,起因次要在于:@vue/composition-api 是作为一个 Vue2 插件存在,无奈间接侵入 Vue2 源码,导致局部能力无奈实现或会带来额定的性能开销,例如 flush: 'post'ref 主动解包等。咱们也看到在最新的 Vue2.7 版本中,也是在运行时框架里从新实现了这部分内容,以躲避上述问题。

下图展现了 Mpx 中响应式 API 外围模块依赖关系:

数据响应限度带来的差别

因为 Object.defineProperty 的能力限度,Mpx 存在和 Vue2 统一的数据响应限度,无奈感知到对象 property 的增加和删除以及数组的索引赋值,与 Vue2 统一,咱们裸露了 setdel API 来让用户显式地进行相干操作。除此之外,因为应用形式产生了变动,咱们在应用 reactive API 创立响应式数据时,还会遇到新的限度,咱们来看一下代码示例:

import {reactive, watchSyncEffect, set} from '@mpxjs/core'

const state = reactive([0, 1, 2, 3])

watchSyncEffect(() => {console.log(JSON.stringify(state)) // [0,1,2,3]
})

set(state, 1, 3) // 不会触发 watchEffect

state.push(4) // 不会触发 watchEffect

能够看出,即便咱们应用了 set API 和数组原型办法对数组进行批改,咱们依然无奈监听到数据变动。

雷同的限度在应用 Object.defineProperty 的 Vue2.7 中也同样存在。

为什么会存在这个限度呢?起因在于:基于 Object.defineProperty 实现的数据响应零碎中,咱们会对对象的每个已有属性创立了一个 Dep 对象,在对该属性进行 get 拜访时通过这个对象将其与依赖它的观察者 ReactiveEffect 关联起来,并在 set 操作时触发关联 ReactiveEffect 的更新,这是咱们大家都晓得的数据响应的基本原理。然而对于新增 / 删除对象属性和批改数组的场景,咱们无奈当时定义以后不存在属性的 get/set (当然这在 proxy 当中是可行的),因而咱们会把对象或者数组自身作为一个数据依赖创立 Dep 对象,通过父级拜访 该数据时定义的 get/set 将其关联到对应的 ReactiveEffect,并在对数据进行新增 / 删除属性或数组操作时通过数据自身持有的 Dep 对象触发关联 ReactiveEffect 的更新,如下图所示:

须要留神的是,通过父级拜访 是建设 DepReactiveEffect 关联关系的先决条件,在选项式 API 中,咱们拜访组件的响应式数据都须要通过 this 进行拜访,相当于这些数据都存在 this 这个必要的 父级,因而咱们在应用 $set/$delete 进行对对象进行新增 / 删除属性或对数组进行批改时都能失去合乎预期的后果,惟一的限度在于不能新增 / 删除根级数据属性,起因就在于 this 不存在拜访它的父级。

然而在组合式 API 中,咱们不须要通过 this 拜访响应式数据,因而通过 reactive() 创立的响应式数据自身就是根级数据,咱们天然无奈通过上述形式感知到根级数据本身的变动(在 Vue3 中,基于 proxy 提供的弱小能力响应式零碎可能准确地感知到数据属性,甚至是以后不存在属性的拜访与批改,不须要为数据本身建设 Dep 对象,天然也不存在相干问题)。

在这种状况下,咱们就须要用 ref() 创立响应式数据,因为 ref 创立了一个包装对象,咱们永远须要通过 .value 来拜访其持有的数据(不论是显式拜访还是隐式主动解包),这样就能保障 ref 数据本身的变动可能被响应式零碎感知,因而也不会遇到下面形容的问题,如下所示:

import {ref, watchSyncEffect, set} from '@mpxjs/core'

const state = ref([0, 1, 2, 3])

watchSyncEffect(() => {console.log(JSON.stringify(state.value)) // [0,1,2,3]
})

set(state.value, 1, 3) // [0,3,2,3]

state.value.push(4) // [0,3,2,3,4]

响应式 API 与 Vue3 中的区别

咱们来总结一下 Mpx 中响应式 API 与 Vue3 中的区别:

  • 不反对 raw 相干 API(markRaw 除外,咱们提供了该 API 用于跳过局部数据的响应式转换)
  • 不反对 readonly 相干 API
  • 不反对 watchEffectwatchcomputed 的调试选项
  • 不反对对 mapset 等汇合类型进行响应式转换
  • 受到 Object.defineProperty 实现带来的数据响应限度影响

对于响应式 API 的更多信息能够查看这里。

生态周边适配

除了 Mpx 运行时外围提供了组合式 API 反对外,咱们对 Mpx 的周边生态能力也都进行了组合式 API 适配反对,包含 storei18nfetch 等。

Pinia store 反对

Pinia 是基于组合式 API 设计的全新数据管理计划,目前曾经取代 Vuex 成为 Vue3 官网举荐的 store,咱们在钻研了 pinia 的设计实现后,对其简练优雅的设计思维及其与组合式 API 的高度适配十分称心(特地是在应用 setup 函数创立 store 时,应用心智与编写组件完全一致,能够将其视作是没有视图的组件)。因而咱们 fork 了 pinia 的源码仓库,基于 Mpx 提供的数据响应能力对其进行了适配革新,使其在 Mpx 环境下也能失常运行,目前相干代码保护在 @mpxjs/pinia 中,在组合式 API 中的简略应用示例如下:

import {createComponent, ref, computed, toRefs} from '@mpxjs/core'
import {defineStore} from '@mpxjs/pinia'

// 应用组合式 API 创立 pinia store 的应用心智与 setup 函数完全一致,强烈推荐
const useSetupStore = defineStore('setup', () => {const count = ref(0)
  const doubleCount = computed(() => count.value * 2)

  function increment () {count.value++}

  return {count, doubleCount, increment}
})

createComponent({setup () {const store = useSetupStore()
    // store 同 props 相似是一个 reactive 对象,解构数据需应用 toRefs 以保持数据响应性
    const {count, doubleCount} = toRefs(store)
    // 办法能够间接解构
    const {increment} = store
  
    return {count, doubleCount, increment}
    //
  }
})

Mpx 中通过 createStore 创立的类 Vuex store 在组合式 API 中依然能够应用,咱们能够在 setup 函数中援用 store 实例进行数据读取与办法调用,不过整体应用体验与 pinia store 存在较大差距,咱们还是举荐在组合式 API 开发中优先应用 pinia store 作为数据管理计划。

I18n 反对

传统选项式 API 中,咱们应用 this.$t 办法在组件内调用翻译函数,但在组合式 API 中咱们无法访问 this,为此咱们参考了 Vue I18n 最新的 9.x 版本,该版本针对 Vue3 及组合式 API 进行了重构适配,提供了全新的 useI18n API,简略应用示例如下:

<template>
  <view>{{t('message.hello')}}</view>
  <button bindtap="changeLocale">change locale</button>
</template>

<script>
  import {createComponent, useI18n} from '@mpxjs/core'

  createComponent({setup () {
      // useI18n 不传参数时指向全局 i18n 对象,也能够传递 locale 和 messages 配置创立部分 i18n 对象
      const {t, locale} = useI18n()

      function changeLocale () {locale.value = locale.value === 'zh-CN' ? 'en-US' : 'zh-CN'}
      // 返回的翻译办法名必须为 t,不能进行重命名
      return {t, changeLocale}
    }
  })
</script>

下面示例代码看上去像是咱们在模板上间接调用 setup() 返回的 t 翻译办法,然而相熟小程序开发的同学都晓得在小程序架构下这是不可能的,示例中的写法其实由框架通过编译 + 运行时伎俩实现的语法糖,咱们会在模板编译时定向扫描 t/te/tm 等 i18n 办法,将其转换为计算属性注入到运行时当中,这就意味着如果咱们对翻译办法进行重命名,模板编译时无奈辨认出 i18n 办法调用,天然也就无奈失常运行。

Mpx 中 i18n 提供了两种实现模式,别离是 wxs 和 computed,能够应用编译选项中的 i18n.isComputed 进行切换,两种形式各有优劣,其中:

  • wxs 模式的劣势在于逻辑层和视图层独立保护语言集,无额定运行时性能开销,且应用没有任何限度;劣势同样源于语言集同时存在于逻辑层(js)和视图层(wxs)当中,这部分的包体积占用翻倍;
  • computed 模式的劣势在于语言集只存在于逻辑层中,无额定包体积占用,且能够通过动静增加语言集的形式进一步缩小包体积占用;劣势则是会产生额定的运行时性能开销,且应用上存在限度,模板调用时无奈间接拜访 wx:for 中的 itemindex

在组合式 API 中模板上应用 useI18n() 返回的翻译函数 t/te/tm 时,为了残缺实现 useI18n API 的性能,会强制应用 computed 模式进行实现,这也意味着该用法会受到 computed 模式应用限度的影响。不过当你不须要应用 useI18n 承受 messages 参数创立部分语言集作用域性能时,你也齐全能够在模板中持续应用原有的 $t/$tc/$te/$tm 办法,这些办法受编译选项 i18n.isComputed 的影响,同时指向全局语言集作用域。

更多对于生态周边的组合式 API 使用指南能够点击下方链接查看详情:

  • store
  • i18n
  • fetch

输入 web 适配

跨端输入 web 作为 Mpx 的一大外围个性,在业务中存在宽泛应用,同时也是咱们设计实现任何框架新个性须要优先思考的事项。在本次组合式 API 反对中,咱们从设计之初就思考了跨端输入 web 的适配反对,保障应用 Mpx 组合式 API 开发的业务代码都能在 web 环境中失常运行。

咱们输入 web 的整体技术方向在于尽可能复用 Vue 已有的生态能力,为了实现这个指标,咱们须要提供尽可能与 Vue 保持一致的 API 设计,以升高抹平适配老本。在输入 web 时,外围组合式 API 基于 Vue2.7 版本中的已有能力进行适配提供,简略举个例子:对于 import {ref} from 'mpxjs/core' 这行语句,在小程序中会指向 Mpx 外部保护的 ref 实现,而在输入 web 时会指向 Vue 中保护的 ref 实现,两者的实现尽管不仅雷同,但只有保障对外函数签名统一,对于开发者用户来说就无感知。

咱们借助了 Mpx 弱小的条件编译能力进行上述实现,对运行时导出依据输入平台进行重定向,这样还能保障跨端输入产物洁净简洁,仅蕴含以后输入环境下必要的逻辑,如下图所示:

同理,咱们也采纳了相似的形式实现了组合式 API 周边能力对于输入 web 的适配反对,如 pinia store 应用 pinia 原始版本进行适配实现,而 i18n 能力则是应用 [email protected] + vue-i18n-bridge 进行适配实现。

性能体现

性能是 Mpx 始终以来的外围关注点,咱们对组合式 API 的最终实现版本进行了一系列性能评估测试,咱们应用组合式 API 版本对业务中的评估组件进行了重构,评估组件属于咱们业务中交互及性能绝对比较复杂的组件,源码行数约 1000 行,组件数据 27 项,组件办法 18 个,咱们在测试项目中对选项式 API 和组合式 API 两个版本实现的组件进行了一系列测试。

组件初始化耗时

因为组合式 API 扭转了原有的组件初始化流程,咱们对组件的初始化耗时进行了重点测试,测试口径如下:

  • 耗时计算以挂载组件为终点,以组件 ready 执行为起点
  • 测试后果为 10 次手工测试排除最大最小值后求均值
  • IOS 测试机型为 iPhone 13 pro max,安卓测试机型为 OPPO R9

结果显示两个版本的组件初始化耗时大抵持平,不分优劣。

IOS 安卓
选项式 API 42.5ms 366.6ms
组合式 API 42.4ms 370.1ms

组件 JS 体积

在构建产物体积方面,因为组合式 API 的写法对于 JS 代码压缩更加无利,同样的逻辑实现下,组合式 API 版本的组件构建压缩后 JS 体积稍逊一筹。

组件 JS 体积
选项式 API 15.67KB
组合式 API 13.60KB

框架运行时体积

在 Mpx2.8 版本中,咱们在框架运行时中新增了组合式 API 相干实现,不过通过优化运行时导出,使其对 tree shaking 更加敌对,咱们的框架运行时体积在理论构建产物中没有产生太大增长。

框架运行时体积
选项式 API 51.66KB
组合式 API 57.47KB

综上所述,组合式 API 版本的运行时性能与选项式 API 大抵持平,在包体积占用方面,新版框架运行时体积占用略有晋升,不过因为组合式 API 开发模式对代码压缩更敌对,加上组合式 API 更易进行逻辑复用的特点,咱们预计在理论业务我的项目中,组合式 API 的包体积占用会更小。

破坏性扭转

Mpx 组合式 API 版本齐全兼容原有的选项式 API 开发方式,不过咱们在运行时重构过程中仍然带来了大量的破坏性扭转,详情如下:

  • 框架过往提供的组件加强生命周期 pageShow/pageHide 与微信原生提供的 pageLifetimes.show/hide 齐全对齐,不再提供组件初始挂载时必然执行 pageShow 的保障(因为组件可能在后盾页面进行挂载),相干初始化逻辑肯定不要搁置在 pageShow 当中;
  • 勾销了框架过来提供的基于外部生命周期实现的非标准加强生命周期,如 beforeCreate/onBeforeCreate 等,间接将外部生命周期变量导出提供给用户应用,详情查看这里;
  • 为了优化 tree shaking,作为框架运行时 default exportMpx 对象不再挂载 createComponent/createStore 等运行时办法,一律通过 named export 提供,Mpx 对象上仅保留 set/use 等全局 API,详情查看这里;
  • 应用 I18n 能力时,为了与新版 vue-i18n 放弃对齐,this.$i18n 对象指向全局作用域,如需创立部分作用域须要应用组合式 API useI18n 的形式进行创立。
  • watch API 不再承受第二个参数为带有 handler 属性的对象模式(该参数模式只应存在于 watch option 中),第二个参数必须为回调函数,与 Vue 对齐。

更具体的迁徙指南请点击查看这里。

将来布局

在实现编译长久化缓存和组合式 API 反对后,咱们曾经实现了去年布局中最大的两个技术升级,后续咱们的技术布局如下:

  • 反对应用 Vite 进行 web 构建
  • 欠缺 Mpx 跨端输入 Hummer 并正式 release
  • 优化运行时 render 函数,升高包体积占用
  • 内置反对原子类应用
  • Mpx-cube-ui 正式开源

最初,再次感激所有参加 Mpx 组合式 API 技术建设的同学们,也欢送社区同学退出 Mpx 我的项目开源共建。

正文完
 0