找回密码
 立即注册

在 2020 年,谈小程序框架该如何选择

匿名  发表于 2022-1-4 19:16:41 阅读模式 打印 上一主题 下一主题
写在开首,这不是一篇广告文。
微信小法式横空出世,到现在已经有 4 年时候。从一路头只能挑选原生语法,到现在小法式框架 Rax/Taro/uni-app 百花齐放。这背后是小法式原生语法酿成的生态割裂,也是营业对「一码多端」的激烈诉求,更是前端现在繁华的生态系统。
小法式的诞生

微信开了一个头

微信并不是第一个做小法式的 App,而是做小法式最有上风的 App,比如高流量、用户较长的逗留时候等等。站在微信的视角,小法式从营业形式上更像是公众号开辟的演变产物。在更早的时辰,微信经过 sdk 的形式,增强了开辟者开辟公众号网页的才能。小法式的诞生是微信自己迈向平台化超级 App 的营业行为,而且帮助用户更好的实现了「轻量级 Web App」。
微信小法式诞生之初就自己界说了一套”标准“,与前端已有的生态格格不入,最起头的框架甚至没有组件、没有 npm,和 Web 生态严重摆脱。由于特别的双线程模子与四不像的语法,开辟者苦不胜言。小法式的开放只是对三方营业的开放而已。
蜂拥而至的效仿

别的厂商看到了小法式营业的开放性,试图也可以做成平台型 App。付出宝小法式百度小法式、淘宝小法式、360小法式、快利用......它们中的大大都都不谋而合的挑选了和微信类似的架构、框架,而这更多的不是从技术角度去做的决议,而是想尽能够蹭微信小法式的福利,让开辟者可以更快的投放到自己的平台。固然,其中有两个稍显分歧。一个是早期的淘宝小法式,它不但支持 axml 的写法,同时还支持 sfc -- 用 Vue 来开辟,这个架构更洪流平上让开辟者有了挑选的权利,而且可以更好地毗连已有的前端生态。另一个是快利用,也是用类似 Vue 的语法来开辟,可是略显畸形的是它自己又造了一套标准,更像是对 Vue 停止了魔改,开辟者的开辟本钱并没有获得有用的提升。
小法式框架挑选

小法式原生语法 and 增强型框架

小法式原生语法

能否是原生语法一定是被鄙弃的。站在 2020 年这个时候节点上来说,并不是这样。纯真就微信小法式 or 付出宝小法式而言,今朝的小法式生态是完完全全充足开辟者操纵前端已有的部分生态来开辟出合适预期的利用的。
与早期 npm 才能的缺失、只能经过模板衬实在现组件化相比而言。现在的小法式已经可以做到前端工程化,而且植入前端生态中已有的一些理念,例如状态治理、CLI 工程化等等。
也就是说,当营业的需求只要投放到微信小法式大概付出宝小法式的时辰,原生语法完完全全可以成为前端法式员们的一个挑选。你可以组件化你的项目,你可以手写一个大概利用社区已有的状态治理库来颗粒化治理组件状态,你甚至还可以间接用 TypeScript 来编写你的利用。总之,你几近可以把你所习惯的工具都带到小法式这个域里。
渐进增强型框架

所谓渐进增强型框架,更多的还是在小法式引入 npm 以后,有了加倍开放的才能所带来的收益。这类框架一般仍然是以小法式原生语法为主,只是在逻辑层引入了增强语法来优化利用性能大概供给更便利的利用方式,
以腾讯开源的 omix 框架为例,先简单看一下它的用法:
逻辑层
create.Page(store, {
  // 声明依靠
  use: ['logs'],
  computed: {
    logsLength() {
      return this.logs.length
    }
  },
  onLoad: function () {
    //响应式,自动更新视图
    this.store.data.logs = (wx.getStorageSync('logs') || []).map(log => {
      return util.formatTime(new Date(log))
    })
    setTimeout(() => {
      //响应式,自动更新视图
      this.store.data.logs[0] = 'Changed!'
    }, 1000)
  }
})
视图层
<view class="container log-list">
  <block wx:for="{{logs}}" wx:for-item="log">
    <text class="log-item">{{index + 1}}. {{log}}</text>
  </block>
</view>先不谈它的语法能否合适直觉大概好用。简单来说,它整体保存小法式已有的语法。可是在此根本之上,对它停止了扩大和增强,比如引入了 Vue 中比力有代表性的 computed,比如可以间接经过 this.store.data.logs[0] = 'Changed' 点窜状态。可以说是在小法式原生半 Vue 半 React 的语法(此处只是数目词)布景下,完全将其 Vue 化的一种计划。
利用增强型框架最大的益处是,你可以在只引入少少依靠,而且保存对小法式认知的情况下,用加倍舒爽的语法来写代码。这类框架对于方针只投放到特定平台小法式的开辟者大概非专业锹剿而言是比力好的挑选之一。由于你只需要关注很少的新增文档和小法式本身的文档就充足了。究竟在鞭策某项技术的进程中,团队的进修本钱也是需要斟酌的。
转换类框架

相比于渐进增强型框架,转换类框架的使命是完全分歧的。转换类框架的使命是让开辟者几近不用感受小法式原生语法,更洪流平对接前端已有生态,而且可以实现「一码多端」的营业诉求,只是最初的构建产物为小法式代码。随着这几年的成长,转换类框架大的方面分为两种 -- 编译时/运转时。下文会别离针对两种计划停止分析。

在 2020 年,谈小法式框架该若何挑选-1.jpg

Rax 编译时/Taro 2.0

望文生义,编译时计划的焦点是经过编译分析的方式,将开辟者写的代码转换成小法式原生语法。这里以 Rax 编译时和 Taro 2.0 为例,面向开辟者的语法是类 React 语法,开辟者经过写有一定语法限制的 React 代码,最初转换产物 1:1 转换成对应的小法式代码。

在 2020 年,谈小法式框架该若何挑选-2.jpg

以一段简单的代码为例:
Rax:

import { createElement, useEffect, useState } from 'rax';
import View from 'rax-view';

export default function Home() {
  const [name, setName] = useState('world');
  useEffect(() => {
    console.log('Here is effect.');
  }, [])
  return <View>Hello {name}</View>;
}转换以后的小法式代码:

逻辑层
import { __create_component__, useEffect, useState } from 'jsx2mp-runtime/dist/ali.esm.js'

function Home() {
  const [name, setName] = useState('world');
  useEffect(() => {
    console.log('Here is effect.');
  }, []);

  this._updateData({
    _d0: name
  });
}

Component(__create_component__(Home));
视图层
<block a:if="{{$ready}}">
  <view class="__rax-view">{{_d0}}</view>
</block>编译时计划最大的特点就是,开辟者虽然写的是类 React 语法,可是转换后的代码和渐进增强型框架很是类似。开辟者可以比力清楚的看出编译前后代码的对应关系
简单来说,编译时计划会经过 AST 分析,将开辟者写的 JSX 中 return 的模板部分构建到视图层,残剩部分代码保存,然后经过运转时垫片模拟 React 接口的表示。
以一个简单的 return <View>Hello world</View> 为例,假如想要提取到 <View>Hello world</View>,你可以写这段剖析代码:
// 省略界说 babel parser 和包装 traverse 的部分
const code = fs.readFileSync(FILE_PATH);
const ast = parser(code);
traverse(ast, {
  ReturnStatement(path) {
    const targetNodePath = path.get('argument');
    if (targetNodePath.isJSXElement()) {
      // 假如 return 的子元素是一个 JSX Element 就收集 or 处置一下
    }
  }
})
targetNodePath 就是 <View>Hello world</View> 的节点途径,关于 AST 相关的文章可以自行搜索一下,babel 的 handle book 已经比力具体了,再加上这个帮助网站根基是没有什么门坎的。
可是这个计划实在是存在明显的上风和优势的。
上风


  • 运转时性能消耗低
  • 方针代码明白,开辟者所写即所得
  • 运转时、编译时优化
在这个计划中,你可以轻易的做到和渐进增强型框架一样的结果,即赐与开辟者更多的语法支持以及默许的性能优化处置,比如避免屡次 setData,亦或是长列表优化等等。
优势


  • 语法限制高
由于需要完全射中开辟者在模板部分所用到的一切语法,这就对编译时框架的实现者有相当高的要求。由于大部分前端开辟者们实在已经对灵活的语法有一定的依靠性,比如会利用高阶组件,比如在条件判定的时辰写很多 return 等等。进一步的,由因而 1:1 编译转换,开辟者在开辟的时辰还是不能不去遵守小法式的开辟标准,比如一个文件中界说只能界说一个组件之类的。
今朝在阿里巴巴团体内部,Rax 的这套编译时计划已经落地了很多营业,包括「电影表演」小法式等,从开辟者的理论来看,假如可以把握编译时开辟的技能,即保证终极 return 的模板的简洁性,语法限制实在还是在可以接管的范围内的。
Rax 运转时/Remax/Taro Next

运转时计划相比于上面的编译时计划,最大的上风是可以几近没有任何语法约束的去完成代码编写。这对于开辟者而言,无疑是最大的吸引力,高阶组件用起来!createProtal 用起来!可是在小法式范畴上临时还不成能存在这么好的工作,这也是小法式原生语法最初的固执。没有语法限制带来的更多的性能上的牺牲,这个与运转时计划的实现方式有很大的关系,接下来我具体先容一下。
从衬着的角度来看,这套计划更切近于富文本衬着。逻辑层将一个和节点衬着信息相关的组件树传递给视图层,视图层经过节点范例判定然落后行视图衬着。下面这个图简要的描写了一下全部进程:

在 2020 年,谈小法式框架该若何挑选-3.jpg

虽然只用了保护两个字,可是逻辑层做的工作实在比力复杂。首先要做的是,去向置节点间的关系,去模拟 appendChild/ removeChild/updateNode 等各个行为来操纵 VDOM 树。其次比力重要的是去模拟事务,在逻辑层每一个节点类会继续自 EventTarget 基类,这个和 W3C 是一样的,然后经过 nodeId 作为标识去收集需要监听的事务,当视图层经过 action 触发了某个节点的事务以后,再经过原生小法式事务中的 event.currentTarget.dataset.nodeId获得到方针节点的 id,终极触发方针回调。
由于本文篇幅题目,不会加倍具体的先容其中的各个部分加倍具体的实现,感爱好的同学可以经过  Rax 的源码大概 npm init rax demo 起一个项目经过终极的产物来研讨全部道理。
在今朝这个阶段,即使是运转时计划,也有分歧的实现思绪。以 Kbone (Rax 运转时计划是从 Kbone 革新而来) 和 Taro Next 都是经过模拟 Web 情况来完全对接前端生态,而 Remax 只是简单的经过 react reconciler 毗连 React 和小法式。
从营业诉求来看,笔者以为,Rax 和 Taro Next 能够会比 Remax 加倍开放。首先,需要斟酌是三部分的诉求,(1)毫无语法限制,既然已经没有了语法限制,为什么不能用前端加倍熟悉的方式来开辟,即具有操纵 DOM 的权利;(2)反面 DSL 耦合,虽然在阿里巴巴团体内,对 React 的认可度更高,可是从实现道理上来看,和某个框架停止强绑定一定不是最优解;(3)旧有的 Web 营业迁移,明天我们所面临的开辟者,很多都是由于营业压力大概其他情况需要将原本的 Web 页面迁移到小法式上,那末用模拟 Web 情况这套计划是最好不外了,按照我们的测试,大部分营业几近可以无缝迁移过来。
害!说了这么多标致话,运转时计划真的很香,但这并不是救世主,我来说说它的优势。优势 1:数据传输量大,我们需要将完整的组件树在逻辑层传输到视图层;优势 2:页面上存在大量的监听器,每一个组件都需要无时无刻监听一切的事务,在事务不竭触发的进程中,经过 nodeId 挑选出真正需要触发的事务;优势 3:模板递归衬着,假如利用原生语法,原生框架可以在衬着前就晓得页面大要的结构,来对衬着停止优化,可是假如仅仅只是经过类似 <view a:if="{{node.tagName === 'view'}}"></view> 这样的信息,是很难判定页面的实在结构的。
组合

鱼和熊掌虽然不能兼得,可是可以各要一半~再次夸大,本文不是广告文。假如编译时和运转时计划共存呢?基于淘系锹剿高度现代的工程化堆集,开辟者已经习惯经过区块来组建项目。更得益于,Rax 在编译时和运转时计划都有所堆集,我们希望可以将运转时计划和编译时计划组合利用。对于根本复杂大概对于性能有要求的模块经过编译时实现。然后再经过 npm 包的形式,引入到运转时的项目中去,从而有用下降了运转时计划的性能消耗,而且能保证绝大部分的营业场景可以用无穷制的语法完成,而开辟者所面临的都是 Rax DSL。
用一个 Demo 来看下:
// 这是一个倒计时组件,经过编译时实现,然后公布为 rax-taobao-countdown
import { createElement } from 'rax';
import View from 'rax-view';

function CountDown(props) {
  // 省略各类逻辑...
  return <View>{day}:{hours}:{minutes}:{seconds}</View>
}

export default CountDown;
// 运转时项目
import { createElement } from 'rax';
import CountDown from 'rax-taobao-countdown';

function Home() {
  return <CountDown now={Date.now()} />
}假定,我们这个倒计时组件结构很是复杂,而且要求极高的交互性。那末,开辟者可以经过编译时计划开辟一个高性能 CountDown 组件,然后在运转时项目中引入利用。此时,视图层所获得的节点树信息大致以下:
{
  "tagName": "custom-component",
  "type": "element",
  "behavior": "CountDown",
  "children": []
}而不会有更多更深层结构的节点信息,有用避免刚刚说的运转时计划中存在的优势。
Web 才是未来

小法式原生语法绝对不是小法式 or 下一代的衬着计划。经过微信小法式现有的语律例范来对开辟者停止绑架,只会让更多的人想冲破围城。微信小法式似乎已经意想到了这一点,从今朝的迭代来看,微信小法式引入了越来越多 Web 已有的工具,包括经过 wxs在视图层便可以一定水平上操纵 DOM,甚至获得到逻辑层组件实例等等,这个可以给现有的转换类框架供给更多的能够性。可是,假如小法式假如一路头设想的不这么糟糕呢,我们能够会失业(开个玩笑)?
对于营业的开辟者而言,「一码多端」才是效力最大化的。明天的营业需求能够只是投放到小法式容器,明天的需求能够就是投放到 Web,未来甚至 是 Flutter。Web 是最切近前端开辟者的,有构造保障(W3C)的标准。所以,站在 2020 年这个时候点,不管是框架供给者,还是营业开辟者都应当更多的从标准的角度思考题目,这样才能让营业代码有更多的能够性。
总结

间隔小法式诞生已经曩昔很多年,2020 年应当若何挑选营业合适的小法式框架,这个需要开辟者权衡利弊以后再做出挑选。由于每个营业的形式分歧,利用的存活时候也不不异,按照自己的需要挑选能够步崆最好的,本文只是从一个全局的视角对一切范例的框架停止分析,希望可以让正在看文章的你,不那末纠结~
招聘

假如大师对我说的「一码多端」感爱好,大概对前端架构感爱好。可以斟酌加入我们,团队今朝有终端架构、Node 架构、Serverless 研发平台等多个偏向。
联系邮箱:fushen.jzw#http://alibaba-inc.com (# => @)
回复

使用道具

大神点评

匿名  发表于 2022-1-4 19:17:17
很希奇,那为什么阿里一路头要模仿微信小法式,而不是用一套更合适前端开辟体验的写法呢?
回复

使用道具

匿名  发表于 2022-1-4 19:17:54
可以看下“蜂拥而至的效仿”这一节
回复

使用道具

匿名  发表于 2022-1-4 19:18:08
“假如小法式假如一路头设想的不这么糟糕呢,我们能够会失业”
[摊手]
回复

使用道具

匿名  发表于 2022-1-4 19:18:42
[飙泪笑]看到了
回复

使用道具

匿名  发表于 2022-1-4 19:19:04
大大都的小法式用原生说话开辟充足了
回复

使用道具

匿名  发表于 2022-1-4 19:19:39
嗯…按照自己的营业需求和未来的结构来挑选合适自己的就好
回复

使用道具

匿名  发表于 2022-1-4 19:20:08
Taro、Rax: 似乎未来无所作为的跨端小法式框架就我俩了,你说当初微信一路头就写好一个优异的技术系统多好,搞得现在还要我哥俩来做组件化和ts化,只怪产物司理三天后就要,否则也没我俩的戏份,希望有一天堂内有个小法式标准委员会hhhh
回复

使用道具

匿名  发表于 2022-1-4 19:21:04
我是一位大三的门生,现在教员有个小法式项目可以做,可是我想走web偏向  这该若何决定
回复

使用道具

匿名  发表于 2022-1-4 19:21:54
rax.js.org 接待利用 Rax,用 Web 的方式开辟小法式
回复

使用道具

说点什么

您需要登录后才可以回帖 登录 | 立即注册
HOT • 推荐

神回复

站长姓名:王殿武 杭州共生网络科技 创始人 云裂变新零售系统 创始人 飞商人脉对接平台 创始人 同城交友聚会平台 创始人 生活经验分享社区 创始人 合作微信:15924191378(注明来意)