天涯论坛

 找回密码
 立即注册
搜索
查看: 14|回复: 2

小程序底层架构剖析

[复制链接]

3048

主题

119

回帖

9915万

积分

论坛元老

Rank: 8Rank: 8

积分
99159056
发表于 2024-10-3 12:38:41 | 显示全部楼层 |阅读模式

咱们前端切图崽网上冲浪的时候,会发掘非常多技术文案都在分析vue框架,react框架,显少有分析小程序框架的。那今天就经过这篇短小精悍的文案大众认识一下微X小程序的底层架构。(如无特殊说明,下文中说到的小程序都是微X小程序)

小程序的由来

咱们先抛出一个问题,小程序的时候,企业们都在微X里怎么运营? 答案便是小程序的“前身”-公众号,企业们广泛会把H5网站放在公众号做为流量转换的入口。然则h5确实让公众号遇到了有些问题。

首要便是白屏过程针对有些繁杂页面,受限于设备性能和网络速度,白屏会更加显著;再便是缺少操作反馈例如页面切换生硬以及点击所带来的迟滞感等等;

微X团队内部经过JS-SDK以及后来的加强JS-SDK已然能够处理有些问题,然则针对以上问题是JS-SDK所处理不了的,急需一个全新的系统来完成,它需要具备以下能力:

快速加载更强大的能力原生的体验易用且安全的微X数据开放有效,简单的研发

于是,小程序诞生了。

双线程架构

此处点题一下,本文咱们讨论的是小程序的底层架构,其实,双线程架构便是小程序的核心。为何要设计成双线程架构呢?首要咱们来回顾一下浏览器的线程模型,浏览器是一个单线程架构,重点原由是js准许拜访操作DOM,因此呢js线程和渲染线程只能互斥运行。

那小程序又是怎样做到双线程的呢,基本原由便是微X小程序禁止js操作DOM。

运用双线程架构的优良一目了然:

加强用户体验(ui和规律分离,避免页面长期阻塞和卡顿)优化应用性能(运行在区别的线程中,能够同期渲染计算)研发效率更高(解耦和松散耦合)

接下来就带大众认识一下渲染层以及规律层的设计思路。

设计思路-渲染层

标签实现

小程序运用的是Exparser组件模型,Exparser组件模型与Web Components中的shadow DOM高度类似微X为何运用自定义组件框架,而不运用Web Components呢?重点还是出于安全思虑,并且方便管控。既然Exparser组件框架与shadow DOM高度类似那样咱们首要认识一下shadow DOM。

shadow DOM: Web Components的一个重要属性是封装-能够将标记结构、样式和行径隐匿起来,并与页面上的其他代码相隔离,保准区别的部分不会混在一块,可使代码更加干净、整洁。其中,shadow DOM接口是关键所在,它能够将一个隐匿的,独立的DOM附加到一个元素上。

shadow DOM准许隐匿的DOM树附加到常规的DOM树中-它以shadow root节点为初始根节点,在根节点的下方,能够是任意元素,和普通的DOM同样

以上解释源自于MDN,其实shadow DOM并不奥秘,像咱们非常熟练的video标签本质上便是用shadow DOM实现的。咱们先打开chrome浏览器设置中的“打开用户代理shadow DOM”,而后再点击video标签就能看到。

创建shadow DOM非常简单,直接运用attachShadow办法能够创建。

var shadow = Element.attachShadow({ mode: closed

})

Exparser组件模型:Exparser组件模型参考了shadow DOM并进行了有些修改,像事件系统就是完全复刻的,slot插槽,属性传递等都基本一致。但同期它又拥有有些特点:

基于shadow DOM模型:模型上与Web Components的shadow DOM高度类似,但不依赖浏览器的原生支持,其他依赖库;实现时,还针对性地增多了其他API以支持小程序组件编程;可在纯JS环境中运行:这寓意规律拥有必定的组件树组织能力;有效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同期代码尺寸较小;

WXML编译

认识了小程序的组件系统之后,接下来瞧瞧WXML的编译过程。小程序中的DOM编译流程与vue类似,会先将代码字符串编译为虚拟DOM,小程序中的虚拟DOM结构如下:WXML最后会被编译为JS文件,而后插进到渲染层的script标签中。

WXSS动态适配

WXSS是小程序中运用的样式语言,WXSS拥有CSS的大部分特性,同期它对CSS进行了扩充以及修改。

小程序中运用的尺寸单位为rpx(Responsive px),区别于h5中针对px的处理,需要运用postcss进行统一的转换,小程序底层已然研发者做好了这层转换,那详细它是怎么做到的呢?

咱们看它的这段源码,其实它与阿里的flexible.js方法是类似的,区别的是它做了一个精度收拢的优化,重点是为认识决1px的问题。

WXSS一样会经过编译,最后的编译产物为wxss.js,区别于WXML经过script标签的形式插进到渲染层,wxss.js则是经过eval的方式注入到渲染层代码中。

渲染层webview

全局变量: 渲染线程中存在着以下全局变量。

webviewId:webview的独一标识,当用户打开一个小程序页面的时候,相当于打开了一个webview,区别的webview用webviewid来区分;wxAppCode:全部页面的json wxss wxml编译之后都存储在这儿;Vd_version_info:版本信息;./dev/wxconfig.js:小程序默认总配置项,包含用户自定义与系统默认的整合结果。在掌控台输入__wxConfig能够看出打印结果;./dev/devtoolsconfig.js:小程序研发者配置,包含navigationBarHeight,标题栏的高度,状态栏高度,等等,掌控台输入__devtoolsConfig能够看到其对应的信息;./dev/deviceinfo.js:设备信息,包括尺寸/像素点pixelRatio;./dev/jsdebug.js:debug工具;./dev/WAWebview.js:渲染层底层基本库;./dev/hls.js:优秀的视频流处理工具;./dev/WARemoteDebug.js:底层基本库调试工具;

那小程序是怎样快速起步一个webview的呢?

咱们在打开pages/index/index视图页面时,发掘DOM中多加载了一个__pageframe__/pageframe.html的视图层。这个视图层的功效正是小程序提前为一个新的页面层准备的。小程序每一个视图层页面内容都是经过pageframe.html模板来生成的,包含小程序起步的首页。

下面来瞧瞧小程序为快速打开小程序页面做的技术优化:

首页起步时,即第1经过pageframe.html生成内容后,后台服务会缓存pageframe.html模板首次生成的html内容;非首次新打开页面时,页面请求的pageframe.html内容直接走后台缓存;非首次新打开页面时,pageframe.html页面引入的外链js资源走本地缓存; 这般在后续新打开页面时,都会走缓存的pageframe的内容,避免重复生成,快速打开一个新页面。

视图层打开新页面的流程

在创建每一个视图层页面的webview时,都会为其绑定了onLoadCommit事件(它会在页面加载完成后触发,包括当前文档的导航和副框架的文档加载)。初始时webview的src会被指定为空页面位置http://127.0.0.1{global.proxyPort}/aboutblank?${c},其中c为对应webview的id。webview从空页面到详细页面视图的过程如下:

空页面位置webview加载完毕后执行事件中的reload办法,即设置webview的src为pageframe位置;加载完成后,设置其src为pageframe.html, 新的src内容加载完成后再次触发onLoadCommit事件但按照要求不会执行reload办法;pageframe.html页面在dom ready之后触发注入并执行详细页面关联的代码,此时经过history.pushState办法修改webview的src然则webview并不会发送页面请求;

设计思路-规律

接下来咱们瞧瞧小程序在规律层都做了那些事情。

规律层与视图层通信

在小程序中,规律仅有一个,然则渲染层有多个,渲染层和规律层之间是经过微X客户端进行桥接通信的。那详细是怎么实现的呢?其实它运用便是WeixinJSBridge通信机制。

在小程序执行的过程中,微X客户端分别向渲染层和规律层注入WeixinJSBridge,WeixinJSBridge重点供给了以下几个办法

invoke:调用native API;invokeCallbackHandler:Native 传递 invoke 办法回调结果;publish:渲染层用来向规律业务层发送信息便是说要调用规律层的事件办法;subscribe:订阅规律信息;subscribeHandler:视图层和规律信息订阅转发;setCustomPublishHandler:自定义信息转发;

渲染层怎样规律层通信?

渲染层向规律层通信的方式便是采用事件系统,以上便是完整的事件系统流程。

研发者在DOM上经过@click绑定事件,WXML文件被编译的时候,会经过$gwx函数生成虚拟DOM,而后小程序执行的时候渲染层底层基本库会对虚拟DOM进行解析,事件绑定最后会以attr属性的形式生成到虚拟DOM中,因此底层基本经过applyPropeties解析事件并经过addEventListener绑定到相应DOM并声明回调。

用户点击相应DOM时,Exparser组件系统接收到这个事件,而后起始执行回调。回调函数在规律层,事件的触发在渲染层,此时,小程序会经过setData发送数据到规律层,这个时候WeixinJSBridge就派上用场了,渲染层调用publish办法发送数据,规律经过registercallback进行监听,并执行相应的回调。此时,渲染层到规律层的通信流程结束。

规律层又是怎样将改变后的数据回传给渲染层的呢规律层改变数据之后,一样是触发setData办法而后渲染层经过subscribe进行监听,从eventname和触发事件时候记录的回调函数来判断是哪个事件被触发了,从而获取动态数据。

第三方小程序框架

WXML,WXSS都是小程序的原生研发语言,运用原生语言研发还是存在许多限制,尤其是17年小程序刚推出那会。因此呢,第三方小程序框架应运而生。第三方框架能够分为三大类。

第1类是预编译框架,预编译框架便是在执行前就进行编译。像我司在17年研发“转转二手交易网”的时候运用的wepy框架就属于预编译框架。预编译框架有些显而易见的缺点,这类预编译框架要么是类vue,要么是类React,倘若后期vueReact再出有些新特性的话,预编译框架就要进行扩展编写;还有有些兼容问题,针对小程序本身不支持的有些属性,预编译框架需要进行兼容;

第二类是半编译半运行框架,像美团的mpvue便是此类框架,半编译指的是vue的template需要单独编译为wxml,半运行讲的是vue整体的特性都会在规律层中运行。为了符合小程序的渲染框架,修改了vue的框架;

第三类是运行时框架,像Remax便是运行时框架,它能够使研发运用完整的React语法来研发小程序。由于小程序框架本身是不支持js直接操作DOM的,那Remax框架是怎样处理这个问题的呢?其实它自己复刻了一套操作DOM的API,例如appendChild,innterHtml等,然则它真正操作的并不是dom,而是data中的数据结构。从而达到了操作DOM的目的。使得自己真正成为了一个运行时框架;

结语

介绍到这儿,小程序的底层框架原理基本已然介绍完了,想跟大众分享的是,小程序确实和h5非常类似,其实它相当于一个借助了native强大功能的加强版h5,小程序并不奥秘,除了微X小程序之外,此刻各大超级APP都已然推出了自己的小程序,原理应该都大差不差。

本篇文案其实相当于一个学习笔记,作者本身非常想搞清楚微X小程序的架构,然则微X小程序并开源,某次偶然的机会逛掘金的时候看到这篇小册,就全部学习了一下,这里感谢原作者!

参考

https://juejin.cn/book/6982013809212784676





上一篇:百度程序员研发避坑指南(前端篇)
下一篇:短连接转化器有哪些?长链接 短链接转换器有哪些?
回复

使用道具 举报

2946

主题

2万

回帖

9997万

积分

论坛元老

Rank: 8Rank: 8

积分
99979427
发表于 2024-10-4 14:02:52 | 显示全部楼层
“板凳”(第三个回帖的人)‌
回复

使用道具 举报

3089

主题

3万

回帖

9909万

积分

论坛元老

Rank: 8Rank: 8

积分
99098770
发表于 2024-11-5 19:53:57 | 显示全部楼层
太棒了、厉害、为你打call、点赞、非常精彩等。
回复

使用道具 举报

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

本版积分规则

站点统计|Archiver|手机版|小黑屋|天涯论坛 ( 非经营性网站 )|网站地图

GMT+8, 2024-11-23 03:16 , Processed in 0.153831 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.