运行流程

运行流程

来源 https://zhuanlan.zhihu.com/p/36997098javascript

 

一.微信小程序是啥

本质其实就是(混合)的app 介于web app与native 原生app之间,具有丰富的调用手机各类功能的接口,同时又具有灵活性,跨平台css


1. 运行环境差别html


微信小程序运行在三端:iOS、Android 和 用于调试的开发者工具。
三端的脚本执行环境以及用于渲染非原生组件的环境是各不相同的:java

  • 在 iOS 上,小程序的 javascript 代码是运行在 JavaScriptCore 中,是由 WKWebView 来渲染的,环境有 iOS八、iOS九、iOS10
  • 在 Android 上,小程序的 javascript 代码是经过 X5 JSCore来解析,是由 X5 基于 Mobile Chrome 53/57 内核来渲染的
  • 在 开发工具上, 小程序的 javascript 代码是运行在 nwjs 中,是由 Chrome Webview 来渲染的来自官方文档说明

2.小程序目录结web


project
├── pages
| ├── index
| | ├── index.json index 页面配置
| | ├── index.js index 页面逻辑
| | ├── index.wxml index 页面结构
| | └── index.wxss index 页面样式表
| └── log
| ├── log.json log 页面配置
| ├── log.wxml log 页面逻辑
| ├── log.js log 页面结构
| └── log.wxss log 页面样式表
├── app.js 小程序逻辑
├── app.json 小程序公共设置
└── app.wxss 小程序公共样式表json


3.为何小程序比较快canvas

 

2、小程序架构

微信小程序的框架包含两部分View视图层(可能存在多个)、App Service逻辑层(一个),View层用来渲染页面结构,AppService层用来逻辑处理、数据请求、接口调用,它们在两个线程里运行。
视图层使用WebView渲染,逻辑层使用JSCore运行。
视图层和逻辑层经过系统层的WeixinJsBridage进行通讯,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理。小程序


重点讲一下wxs :
因为view 与 App Service是不一样线程,以前是传递数据,当遇到一些数据须要在view中处理时,就能够用wxs来处理,以下所示定义 <wxs module="tools">,使用说明微信小程序


index.js浏览器

//获取应用实例
const app = getApp()
Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false
  },
 //事件处理函数
  bindViewTap: function() {
  },
  onLoad: function() {
  }
})
<!--index.wxml-->
<view class="container">
 <view class="usermotto">
 <text class="user-motto">{{tools.bar(motto)}}</text>
 <text class="user-motto">{{tools.foo}}</text>
 </view>
 <wxs module="tools">
  var foo = "'hello world' from comm.wxs";
  var bar = function(d) {
    return '啥子玩意'+d;
  }
  module.exports = {
    foo: foo,
    bar: bar
  };
 </wxs>
</view>


3、小程序启动加载

运行机制

小程序启动会有两种状况,一种是「冷启动」,一种是「热启动」。 假如用户已经打开过某小程序,而后在必定时间内再次打开该小程序,此时无需从新启动,只需将后台态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的状况,此时小程序须要从新加载启动。


更新机制

小程序冷启动时若是发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序须要等下一次冷启动才会应用上。 若是须要立刻应用最新版本,可使用wx.getUpdateManager API 进行处理。


运行机制

  • 小程序没有重启的概念
  • 当小程序进入后台,客户端会维持一段时间的运行状态,超过必定时间后(目前是5分钟)会被微信主动销毁
  • 当短期内(5s)连续收到两次以上收到系统内存告警,会进行小程序的销毁

 

4、View (页面视图)

视图层由 WXML 与 WXSS 编写,由组件来进行展现。
将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。


一、View - WXML
wxml编译器:wcc 把wxml文件 转为 js 执行方式:wcc index.wxml


二、View - WXSS

  • WXSS(WeiXin Style Sheets)
  • wxss编译器:wcsc 把wxss文件转化为 js 执行方式: wcsc index.wxss

三、View - Component

  • 小程序的组件基于Web Component标准
  • 使用Polymer框架实现Web Component


四、View - Native Component

  • 目前Native实现的组件有 <canvas/> <video/> <map/> <textarea/>
  • Native组件层在WebView层之上

 

5、WebView预加载

每次小程序进入除了当前页面,Native预先额外加载一个WebView
当打开指定页面时,用默认数据直接渲染,请求数据回来时局部更新
返回显示历史View
退出小程序,View状态不销毁


6、App Service(逻辑层)


逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈
一、App( ) 小程序的入口;Page( ) 页面的入口
三、提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
四、每一个页面有独立的做用域,并提供模块化能力。
五、数据绑定、事件分发、生命周期管理、路由管理


运行环境
IOS - JSCore
Android - X5 JS解析器
DevTool - nwjs Chrome 内核


一、App Service - Binding

  • 数据绑定使用 Mustache 语法(双大括号)将变量包起来,动态数据均来自对应 Page 的 data,能够经过setData方法修改数据。
  • 事件绑定的写法同组件的属性,以 key、value 的形式,key 以bind或catch开头,而后跟上事件的类型,如bindtap, catchtouchstart,value 是一个字符串,须要在对应的 Page 中定义同名的函数。


二、App Service - Life Cylce


三、App Service - API
API经过WeixinJSBridge和Native 进行通讯


四、App Service - Router

  • navigateTo(OBJECT)

保留当前页面,跳转到应用内的某个页面,使用navigateBack能够返回到原页面。页面路径只能是五层

  • redirectTo(OBJECT)

关闭当前页面,跳转到应用内的某个页面。

  • navigateBack(OBJECT)

关闭当前页面,返回上一页面或多级页面。可经过 getCurrentPages()) 获取当前的页面栈,决定须要返回几层。


5、小程序开发经验

一、小程序存在的问题
小程序仍然使用WebView渲染,并不是原生渲染
须要独立开发,不能在非微信环境运行 。
开发者不能够扩展新组件。
依赖浏览器环境的js库不能使用,由于是JSCore执行的,没有window、document对象。
WXSS中没法使用本地(图片、字体等)。
WXSS转化成js 而不是css。
WXSS不支持级联选择器。
小程序没法打开页面,没法拉起APP。


二、小程序的优势
提早新建WebView,准备新页面渲染。
View层和逻辑层分离,经过数据驱动,不直接操做DOM。
使用Virtual DOM,进行局部更新。
所有使用https,确保传输中安全。
加入rpx单位,隔离设备尺寸,方便开发。

rpx(responsive pixel):
能够根据屏幕宽度进行自适应。规定屏幕宽为750rpx。
如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,
1rpx = 0.5px = 1物理像素。
设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)
iPhone5 1rpx = 0.42px 1px = 2.34rpx
iPhone6 1rpx = 0.5px 1px = 2rpx
iPhone6Plus 1rpx = 0.552px 1px = 1.81rpx

 

7、代码运行

运行时,外面包裹define,代码做为回到,当调用回调时,只传入前面三个值,因为后面的变量都是局部定义的变量,就屏蔽了(window,document等这些变量.

其中O就是上面define('app.js',callback),的回调,回调值传入了三个参数,屏蔽了其余属性


8、优化建议(官方建议)

setData 工做原理
小程序的视图层目前使用 WebView 做为渲染载体,而逻辑层是由独立的 JavascriptCore 做为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具有数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上经过两边提供的 evaluateJavascript 所实现。即用户传输的数据,须要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再经过执行 JS 脚本的形式传递到两边独立环境。
而 evaluateJavascript 的执行会受不少方面的影响,数据到达视图层并非实时的。


常见的 setData 操做错误
1. 频繁的去 setData
在咱们分析过的一些案例里,部分小程序会很是频繁(毫秒级)的去 setData ,其致使了两个后果:

  • Android 下用户在滑动时会感受到卡顿,操做反馈延迟严重,由于 JS 线程一直在编译执行渲染,未能及时将用户操做事件传递到逻辑层,逻辑层亦没法及时将操做处理结果及时传递到视图层;
  • 渲染有出现延时,因为 WebView 的 JS 线程一直处于忙碌状态,逻辑层到页面层的通讯耗时上升,视图层收到的数据消息时距离发出时间已通过去了几百毫秒,渲染的结果并不实时;

2. 每次 setData 都传递大量新数据
由 setData 的底层实现可知,咱们的数据传输实际是一次 evaluateJavascript 脚本过程,当数据量过大时会增长脚本的编译执行时间,占用 WebView JS 线程,
3. 后台态页面进行 setData
当页面进入后台态(用户不可见),不该该继续去进行 setData ,后台态页面的渲染用户是没法感觉的,另外后台态页面去 setData 也会抢占前台页面的执行。
图片资源

  • 目前图片资源的主要性能问题在于大图片和长列表图片上,这两种状况都有可能致使 iOS 客户端内存占用上升,从而触发系统回收小程序页面。
  • 在 iOS 上,小程序的页面是由多个 WKWebView 组成的,在系统内存紧张时,会回收掉一部分 WKWebView。从过去咱们分析的案例来看,大图片和长列表图片的使用会引发 WKWebView 的回收。

 

代码包大小的优化

开发者在实现业务逻辑同时也有必要尽可能减小代码包的大小,由于代码包大小直接影响到下载速度,从而影响用户的首次打开体验。除了代码自身的重构优化外,还能够从这两方面着手优化代码大小:

  1. 分包加载
    对小程序进行分包,能够优化小程序首次启动的下载时间
  2. 清理没有使用到的代码和资源

目前小程序打包是会将工程下全部文件都打入代码包内,也就是说,这些没有被实际使用到的库文件和资源也会被打入到代码包里,从而影响到总体代码包的大小。
预先加载数据
原理
小程序在启动时,会直接加载全部页面逻辑代码进内存,即使 page2 可能都不会被使用。在 page1 跳转至 page2 时,page1 的逻辑代码 Javascript 数据也不会从内存中消失。page2 甚至能够直接访问 page1 中的数据。
小程序的这种机制差别正好能够更好的实现预加载。一般状况下,咱们习惯将数据拉取写在 onLoad 事件中。可是小程序的 page1 跳转到 page2,到 page2 的 onLoad 是存在一个 300ms ~ 400ms 的延时的。以下图:

由于小程序的特性,彻底能够在 page1 中预先拿取数据,而后在 page2 中直接使用数据,这样就能够避开 redirecting 的 300ms ~ 400ms了。以下图:

渲染view线程和AppServcie是相互独立的,对于AppServcie中js运行不会阻塞view的渲染
官方的示例也是采用这种方式: 先App中请求数据,在index.js使用数据

 

 

 

具体能够参考这篇文档( https://mp.weixin.qq.com/s/EvzQoSwWYUmShtI_MkrFuQ )
有错误的地方欢迎指出,共同进步
最后遇到相关问题开发者社区搜索问题
参考内容:

 

============== End

相关文章
相关标签/搜索