您当前的位置:首页 > 电脑百科 > 程序开发 > 移动端 > 小程序

一起来撸个简易的小程序框架

时间:2020-01-03 17:06:54  来源:  作者:

对于小程序框架实现原理,在支付宝小程序官方文档上有这样一段描述:

与传统的 H5 应用不同,小程序运行架构分为 webview 和 worker 两个部分。webview 负责渲染,worker 则负责存储数据和执行业务逻辑。 1.webview 和 worker 之间的通信是异步的。这意味着当我们调用 setData 时,我们的数据并不会立即渲染,而是需要从 worker 异步传输到 webview。 2.数据传输时需要序列化为字符串,然后通过 evaluateJAVAscript 方式传输,数据大小会影响性能。

概括一下,大致意思是小程序框架核心是通过2个线程来完成的,主线程负责webView的渲染工作,worker线程负责js执行。说到这里,你是不是会产生一个疑问:为什么多线程通信损耗性能还要搞多线程呢? 可能大多数人都知道因为Web技术实在是太开放了,开发者可以为所欲为。这种情况在小程序中是不允许的,不允许使用<iframe>、不允许 <a> 直接外跳到其他在线网页、不允许开发者触碰DOM、不允许使用某些未知的危险API等。但是,仔细想想其实单线程也有能力来阻止用户操作这些危险动作,比如通过全局配置黑名单API、改写框架内部编译机制,屏蔽危险操作...

但是却始终无法解决一个问题:如何防止开发者做一些我们想禁用的功能。因为是一个网页,开发者可以执行JS,可以操作DOM,可以操作BOM,可以做一切事情。so,我们需要一个沙箱环境,来运行我们的js,这个沙箱环境需要可以屏蔽掉所有的危险动作。说了这么多,大致想法如下:

一起来撸个简易的小程序框架

 

关于UI层的渲染,有很多实现方式,比如通过类似VNode -> diff的自定义渲染方式来实现了一个简易的小程序框架:

 

function App (props) {
  const {msg} = props; 
  return () => (
    <div class="main">
      {msg}
    </div>
  )
}

render(<App msg="hello world" />)
复制代码

核心就是通过定义@babel/plugin-transform-react-jsx插件来转换 jsx,生成Vnode,再交给Worker通过Diff,最后通过worker postmsg 来通知渲染进程更新:

let index = 0;
// 得到diff差异
let diffData = diff(0, index, oldVnode, newVnode);
// 通知渲染进程更新
self.postMessage(JSON.stringify(diffData)); 
复制代码

有点麻烦?能不能继承现有框架能力?比如Vue、React。当然可以,我们下面就来介绍基于Vue来实现的demo.

实现一个基于Vue的小程序框架

有了上面的知识,我们先不着急写代码,先来捋一下我们需要什么,首先我们需要实现这样一个能力:渲染层和逻辑层分离,emmm。。。大致我们的小程序是这样的

// page.js 逻辑层
export default {
  data: {
    msg: 'hello Vox',
  },
  create() {
    console.log(window);
    setTimeout(() => {
      this.setData({
        msg: 'setData',
      })
    }, 1000);
  },
}
复制代码
// page.vxml.js 渲染层
export default () => {
  return '<div>{{msg}}</div>';
}
复制代码

这里的渲染层为啥不是类似于微信或者支付宝小程序 wxml,axml这样的呢?当然可以,其实我只是为了方便而已,我们可以手写一个webpack loader 来处理一下我们自定义的文件。这里有兴趣的小伙伴可以尝试一下。不是本次介绍的核心。

好了,上面是我们想要的功能,我们核心是框架,框架层要干的事核心有2个:构造worker初始化引擎;构造渲染引擎。

// index.worker.js 构造worker
const voxWorker = options => {
  const {config} = options;
  // Vue生命周期收集
  const lifeCircleMap = {
    'lifeCircle:create': [config.create],
  };
  // 定义setData方法用于通知UI层渲染更新
  self.setData = (data) => {
    console.log('setData called');
    self.postMessage(
      JSON.stringify({
        type: 'update',
        data,
      })
      ,
      null
    );
  };
  // worker构建完成,通知渲染层初始化
  self.postMessage(
    JSON.stringify({
      type: 'init',
      data: config.data,
    })
    ,
    null
  );
  // 执行生命周期函数
  self.onmessage = e => {
    const {type} = JSON.parse(e.data);
    lifeCircleMap[type].forEach(lifeCircle => lifeCircle.call(self))
  }
}

export default voxWorker;
复制代码

上面代码核心干的事其实并不复杂,也就是:

  1. 收集需要用到的生命周期
  2. 定义setData函数,提供给用户层更新UI
  3. 定义监听函数,处理生命周期函数执行
  4. 通知UI进程开启渲染。

当我们通知UI进程开始渲染的时候,UI进程也就是需要构造Vue实例,进行页面render:

worker.onmessage = e => {
    const {type, data} = JSON.parse(e.data);
    if (type === 'init') {
      const mountNode = document.createElement('div');
      document.body.appendChild(mountNode);
      target = new Vue({
        el: mountNode,
        data: () => data,
        template: template(),
        created(){
          worker.postMessage(JSON.stringify({
              type: 'lifeCircle:create',
            })
            ,
            null);
        }
      });
    }
  }
复制代码

可以看到UI线程在初始化的时候,一并初始化了 worker层传递来的data,并对生命周期进行了声明。当生命周期函数在UI层触发的时候,会通知 worker。在我们的例子中,create 钩子通过setData 进行了一个更新data的动作。我们知道 setData 就是拿到数据进行通知更新:

// UI线程接收到通知消息,更新UI
 if (type === 'update') {
      Object.keys(data).map(key => {
        target[key] = data[key];
      });
    }
复制代码

说到这里,似乎一切都感觉清楚多了,我们用worker执行用户js逻辑,worker内无法操作dom,无法访问window。当我们需要更新dom,可以去通知渲染线程做更新。我们也很容易想到不断地数据传输对性能的损耗,所以我们当然可以做进一步的优化,多个setData可以组合一起发送?就是建立一个通信。其次再看一些,我们的worker再通信传输数据的过程中不断通过字符串的parse和stringify

 

一起来撸个简易的小程序框架

 

 

绿色部分时原生JSON.stringify(), 关于这一块如何提升性能一方面可以通过减少数据传输量,其他的优化也可以参考这里如何提升JSON.stringify()的性能

最后你可能会问,小程序用法都是 <view>, <text> 之类的标签,为啥我这里直接用了 <div>。其实吧, 也就是

的语法糖,写一个 vue组件,组件名称叫view是不是就可以了呢?

 

这里为大家介绍的也只是小程序的冰山一角,内部的容器开放jsBridge能力,离线机制,跨webview通信机制等等有兴趣的可以去探索,当然这里也只是抛砖引玉。

有兴趣的可以查看源码Vox

结语

引用知乎上的一段话:

其实,大家对小程序的底层实现都是使用双线程模型,大家对外宣称都会说是为了:方便多个页面之间数据共享和交互为native开发者提供更好的编码体验为了性能(防止用户的JS执行卡住UI线程)其他好处但其实真正的原因其实是:“安全”和“管控”,其他原因都是附加上去的。因为Web技术是非常开放的,JavaScript可以做任何事。但在小程序这个场景下,它不会给开发者那么高的权限:不允许开发者把页面跳转到其他在线网页不允许开发者直接访问DOM不允许开发者随意使用window上的某些未知的可能有危险的API,当然,想解决这些问题不一定非要使用双线程模型,但双线程模型无疑是最合适的技术方案。

经过上面的介绍,是不是发现小程序其实也就那么回事,并没有多么....这边文章主要希望能让你对经常使用的框架有一个原理性的初步认识,至少我们再用的时候可以规避掉一些坑,或者性能问题。

参考文章:

zhuanlan.zhihu.com/p/81775922

双线程前端框架:Voe.js


作者:muwoo
链接:https://juejin.im/post/5e0d74c96fb9a048401cff8e
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



Tags:小程序框架   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
对于小程序框架实现原理,在支付宝小程序官方文档上有这样一段描述:与传统的 H5 应用不同,小程序运行架构分为 webview 和 worker 两个部分。webview 负责渲染,worker 则负责存储...【详细内容】
2020-01-03  Tags: 小程序框架  点击:(74)  评论:(0)  加入收藏
▌简易百科推荐
一、项目背景随着小程序在用户规模和商业化上取得的极大成功,各大平台都推出了自己的小程序。然而这些平台的小程序开发在语法上又不尽相同,不同平台小程序代码的维护需要投入...【详细内容】
2021-11-05  携程技术    Tags:小程序   点击:(65)  评论:(0)  加入收藏
作者:灰灰来源:JS每日一题 一、背景传统的web开发实现登陆功能,一般的做法是输入账号密码、或者输入手机号及短信验证码进行登录服务端校验用户信息通过之后,下发一个代表登录态...【详细内容】
2021-10-29  Nodejs开发    Tags:微信小程序   点击:(43)  评论:(0)  加入收藏
总结列举微信小程序开放能力清单 硬件能力 蓝牙 NFC读写 连接WIFI设备 开放能力 ...【详细内容】
2021-09-27  软件开发分享    Tags:微信小程序   点击:(60)  评论:(0)  加入收藏
核心商城(CoreShop)介绍核心小程序商城系统(CoreShop) 是基于 Asp.Net 5.0、Uni-App开发、支持可视化布局的小程序商城系统;前后端分离,支持分布式部署,跨平台运行;拥有分销、代理、...【详细内容】
2021-07-20  码农也有梦想    Tags:小程序商城   点击:(115)  评论:(0)  加入收藏
介绍Vue3发布已经有一段时间了,从目前来看,其生态还算可以,也已经有了各种组件库给予了支持,但是不管是Vue3还是Vue2都无法直接用来开发小程序,因此国内一些技术团队针对Vue开发...【详细内容】
2021-07-13  爱分享Coder    Tags:小程序   点击:(204)  评论:(0)  加入收藏
首先明确几个概念1. W3C:指万维网联盟(World Wide Web Consortium),是一个国际的标准的制定机构。2. H5(HTML5,HyperText Markup Language 5的缩写),HTML5 是由W3C制定的新HTML标...【详细内容】
2021-07-06  畅游零和一的海洋    Tags:微信小程序   点击:(153)  评论:(0)  加入收藏
在开发微信公众号时,需要不时请求URL和数据封装。为了不做重复的工作。提取公共部分进行封装。产生了相应的公众类。今天先来写下请求类,代码如下:public class HttpRequestP...【详细内容】
2021-06-16  java浮萍  今日头条  Tags:公共类   点击:(134)  评论:(0)  加入收藏
小程序上线后,改版了很多次,包括一些 Api 接口也有改动。如果你学习一个很久之前的小程序项目是没有意义的,本文推荐的小程序都是最近有更新的。相信在你学习、部署的过程中,不...【详细内容】
2021-06-08    程序猿久一  Tags:微信小程序   点击:(207)  评论:(0)  加入收藏
自从2019年微信公开课Pro在微信之夜演示《跳一跳》以来,微信小游戏已经不知不觉走过的三年,这三年中我们可以明显看到微信对小游戏的扶持,对于微信开发者来说,微信小游戏开发以...【详细内容】
2021-05-25  开课吧科科  今日头条  Tags:微信小游戏   点击:(212)  评论:(0)  加入收藏
学习编程从hello world开始。学习微信小程序开发首先要安装一个微信开发者工具,官网上免费下载童叟无欺,下载完傻瓜式安装即可。 双击微信开发者工具,然后选择小程序,然后点击...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:微信小程序   点击:(268)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条