微信小程序发展历程与技术框架解析:从原生语法到Rax/Taro/uni-app

2024-12-17
来源:网络整理

点击蓝字“前端技术选型”关注我们!

微信小程序诞生已经4年了。一开始只能选择原生语法,现在小程序框架Rax/Taro/uni-app全面开花。这背后是小程序原生语法造成的生态碎片化、业务对“一码多终端”的强烈需求以及当前前端生态的繁荣。

NO.1

小程序的诞生

微信已经开始了

微信并不是第一个做小程序的App,但却是做小程序最有优势的App,比如流量高、用户停留时间长等。从微信的角度来看,小程序更像是公众号发展在业务形态上的演变。此前,微信通过SDK增强了开发者开发公众号网页的能力。小程序的诞生是微信自身走向平台化超级App的商业行为,帮助用户更好地实现“轻量级Web App”。

微信小程序诞生之初就定义了一套“标准”,与现有的前端生态不兼容。最初的框架连组件和npm都没有,与Web生态严重脱节。由于特殊的双线程模型和不同的语法,开发者苦不堪言。小程序开放仅对第三方商家开放。

纷纷效仿

其他厂商看到了小程序业务的开放性,正在尝试做平台应用。支付宝小程序、百度小程序、淘宝小程序、360小程序、快应用……大多都选择了类似微信的架构和框架,而这并不是从技术角度来做的。相反,我们决定尽可能利用微信小程序的优势,以便开发者可以更快地在自己的平台上推出它们。当然,其中两个略有不同。一个是早期的淘宝小程序,不仅支持axml编写,还支持sfc——用Vue开发。这种架构更大程度上赋予了开发者选择的权利,并且能够更好的对接现有的前端生态。另一个是快应用,也是使用与Vue类似的语法开发的,但稍显异常的是,它创建了自己的一套标准,这更像是对Vue的魔改。开发商的开发成本并未得到有效改善。 。

NO.2

小程序框架选择

小程序原生语法及增强框架

小程序原生语法

难道母语语法就必须被鄙视吗? 2020年的这个时间点,情况并非如此。就微信小程序或者支付宝小程序而言,目前的小程序生态完全足以让开发者利用现有前端生态的一部分来开发出符合预期的应用。

相比早期npm能力的缺失,组件化只能通过模板渲染来实现。如今的小程序已经可以实现前端工程化,融入了前端生态中已有的一些概念,比如状态管理、CLI工程等。

也就是说,当业务需求只放入微信小程序或者支付宝小程序时,原生语法完全可以成为前端程序员的选择。您可以组件化您的项目。您可以手工编写一个,也可以使用社区现有的状态管理库来精细化地管理组件状态。您甚至可以直接使用它来编写您的应用程序。简而言之,你几乎可以把你习惯的一切都带入小程序领域。

渐进增强框架

所谓渐进增强框架更多的是小程序引入npm后,更多开放能力带来的好处。这类框架一般仍然使用小程序的原生语法,但在逻辑层引入增强语法,以优化应用程序性能或提供更方便的使用。

以腾讯开源的omix()框架为例,我们简单看一下它的用法:

逻辑层

create.Page(store, {
// 声明依赖
use: <a href="https://astexplorer.net/">'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中比较有代表性的,比如可以直接通过this..data.logs[0] = ''来修改状态。可以说,它是在其原生半Vue半语法(这里half只是量词)的背景下,将小程序完全Vue化的解决方案。

合适开发程序平台选择小程序吗_如何选择合适的小程序开发平台_开发什么小程序比较好

使用增强框架的最大好处是你可以用更舒适的语法编写代码,同时只引入很少的依赖项并保留小程序的知识。对于只针对特定平台上的小程序的开发人员或非专业前端来说,此类框架是更好的选择之一。因为你只需要关注几个新的文档和小程序本身的文档。毕竟,在推广某种技术的过程中,也需要考虑团队的学习成本。

转换类框架

与渐进增强框架相比,转换框架的使命完全不同。转换类框架的使命是让开发者在几乎不体验小程序原生语法的情况下,更大程度的对接现有的前端生态,实现“一份代码,多终端”的业务需求,但最终构建的产品是小程序代码。随着近几年的发展,转换类框架分为两大方面——编译时/运行时。下面将对这两个选项进行分析。

Rax编译时间/Taro 2.0

顾名思义,编译时方案的核心就是通过编译和分析将开发者编写的代码转换为小程序的原生语法。这里我们以Rax编译和Taro 2.0为例。开发人员的语法是类语法。开发者编写具有一定语法限制的代码,最终将产品按照1:1的比例转换成相应的小程序代码。

以一段简单的代码为例:

拉克斯:

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 Hello {name};
}

转换后的小程序代码:

逻辑层

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>

编译时解决方案最大的特点是,虽然开发人员编写的是类语法,但转换后的代码与渐进增强框架非常相似。开发者可以清楚地看到编译前和编译后代码之间的对应关系。

简单来说,编译时解决方案会将开发者编写的 JSX 中的模板部分通过 AST 分析构建到视图层,保留剩余代码,然后通过运行时 shim 模拟界面的性能。

举个简单的例子,如果你想提取出来,可以写这样的解析代码:

// 省略定义 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 处理一下
}
}
})

这是节点路径。大家可以自行搜索AST相关的文章。书上已经说得很详细了。另外,这个【辅助网站()基本上没有门槛。

然而,这种解决方案实际上有明显的优点和缺点。

优点

在这个方案中,你可以轻松达到与渐进增强框架相同的效果,即给予开发者更多的语法支持和默认的性能优化处理,比如避免多次,或者长列表优化等。

缺点

由于模板部分需要完全命中开发者使用的所有语法,这对编译时框架的实现者提出了非常高的要求。因为大多数前端开发者其实已经对灵活的语法有了一定的依赖,比如使用高阶组件、做条件判断时写很多等等。而且,由于1:1的编译转换,开发者还是要开发时遵循小程序的开发规范,比如一个文件中只能定义一个组件。

目前在阿里巴巴集团内部,Rax的编译时解决方案已经在很多业务中落地,包括“电影放映”小程序等。从开发者的实践来看,如果能够掌握编译时开发的技巧,就可以保证 模板的简单性和语法限制实际上都在可接受的范围内。

如何选择合适的小程序开发平台_合适开发程序平台选择小程序吗_开发什么小程序比较好

Rax 运行时 //Taro Next

与上面的编译时解决方案相比,运行时解决方案最大的优点是可以编写几乎没有语法限制的代码。这对于开发者来说无疑是最大的吸引力,使用高端组件!使用它!不过,这样的好东西暂时不可能存在于小程序领域。这也是小程序原生语法最后的固执。语法限制不会再造成性能损失。这和运行时解决方案的实现有很大关系。接下来我会详细介绍。

从渲染的角度来看,该方案更接近于富文本渲染。逻辑层将节点渲染信息相关的组件树传递给视图层,视图层判断节点类型,然后渲染视图。下图简单描述了整个流程:

虽然只用了维护这个词,但逻辑层做的事情其实更复杂。首先要做的是处理节点之间的关系并模拟 // 等行为来操作 VDOM 树。第二个更重要的事情是模拟事件。在逻辑层中,每个节点类都会继承自基类。这一点和W3C是一样的。然后作为标识符来收集需要监控的事件。当视图层触发节点事件后,原生小程序事件中通过...获取目标节点的id,最终触发目标回调。

由于本文的篇幅,我们不会详细介绍各部分更具体的实现。有兴趣的同学可以通过Rax(//rax)的源码或者npm init rax demo启动一个项目,通过最终的产品来研究整个原理。

现阶段,即使是运行时解决方案也有不同的实现思路。 Yi(Rax运行时方案修改)和Taro Next都是通过模拟Web环境完全连接到前端生态系统,只需通过连接和小程序即可。

从业务需求的角度来看,笔者认为Rax和Taro Next可能更加开放。首先,上诉需要考虑三个部分:(1)没有语法限制。既然没有语法限制,为什么前端不能用更熟悉的方式来开发,即拥有对DOM的操作权; (2)不与DSL耦合,虽然在阿里巴巴集团内部比较认可,但从实现原理来看,强绑定于某个框架绝对不是最优方案; (3)旧的Web业务迁移,我们今天面对的很多开发人员由于业务压力或者其他情况需要将原来的Web页面迁移到小程序上,所以最好使用模拟的Web环境。根据我们的测试,大多数业务几乎可以无缝迁移。

有害!说了这么多漂亮话,运行时解决方案确实很棒,但它并不是救世主。先说一下它的缺点。缺点一:数据传输量大,我们需要将完整的组件树从逻辑层传输到视图层;缺点二:页面有大量监听器,每个组件需要时刻监听所有事件。当事件不断触发时,在此过程中,通过筛选出真正需要触发的事件;缺点3:模板递归渲染。如果使用原生语法,原生框架可以在渲染之前知道页面的大致结构,从而优化渲染。但仅仅通过这样的信息很难做出判断。页面的实际结构。

组合

虽然不能鱼与熊掌兼得,但可以各占一半。再次强调,本文不是广告。如果编译时和运行时解决方案共存怎么办?基于淘宝前端高度现代化的工程积累,开发者已经习惯了通过区块来构建项目。更重要的是,Rax在编译时和运行时解决方案方面都积累了经验。我们希望能够结合使用运行时解决方案和编译时解决方案。具有复杂基础或性能要求的模块在编译时实现。然后以npm包的形式引入到运行时项目中,有效降低了运行时解决方案的性能损失,保证大部分业务场景都可以用无限制的语法完成,而开发者面对的就是Rax DSL。

用一个 Demo 来看一下:

// 这是一个倒计时组件,通过编译时实现,然后发布为 rax-taobao-countdown
import { createElement } from 'rax';
import View from 'rax-view';

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

export default CountDown;

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

function Home() {
return
}

假设我们的倒计时组件结构非常复杂,并且需要极高的交互性。然后,开发人员可以通过编译时解决方案开发高性能组件,然后将其引入到运行时项目中。此时视图层获取到的节点树信息大致如下:

{
"tagName": "custom-component",
"type": "element",
"behavior": "CountDown",
"children": []
}

不会再有更深层次结构的节点信息,有效避免了刚才提到的运行时方案的缺点。

NO.3

网络是未来

小程序的原生语法绝对不是小程序或者下一代的渲染方案。通过微信小程序现有的语法规范绑架开发者,只会让更多的人想要冲破重围。微信小程序似乎已经意识到了这一点。从目前的迭代来看,微信小程序引入了越来越多Web上现有的东西,包括能够在视图层通过wxs对DOM进行一定程度的操作,甚至获取逻辑。层组件实例等。这可以为现有的转换类框架提供更多的可能性。但如果小程序一开始就设计得不是那么糟糕,我们可能会失业(开个玩笑)?

对于业务开发者来说,“一码多终端”实现效率最大化。今天的业务需求可能只放到小程序容器中,明天的需求可能放到Web中,甚至未来更多。 Web 是最接近前端开发人员的,具有组织保证(W3C)规范。因此,在2020年这个时间点上,无论是框架提供者还是业务开发者都应该更多地站在标准的角度去思考,这样业务代码才能有更多的可能性。

NO.4

总结

小程序诞生至今已经过去很多年了。 2020年如何选择适合业务的小程序框架,需要开发者权衡利弊后做出选择。由于每个业务的形态不同,应用的生存时间也不同。根据自己的需求来选择可能是最好的。本文仅从全局角度分析各类框架。希望可以让正在看文章的人,不要那么纠结~


在看点这里

分享