小程序开发 APP:实现一次开发,动态更新,体验接近原生

2024-07-13
来源:网络整理

背景

我们都知道小程序的体验比直接在App内嵌h5的体验要好,也都知道小程序其实是运行在App上的。那么我们为什么不能用小程序来开发App呢?这样一来,我们不仅可以只开发小程序和App一次,而且一举两得。我们还可以动态更新App,而不需要提交到应用市场审核。我们只需要为小程序载体做一个App的外壳(类似微信小程序SDK),体验效果接近原生。做一个类似这样的小程序平台,把我们现在的App项目框架从组件化改成小程序平台框架。

每个业务程序都是一个提供原生能力的小程序。

什么是小程序

首先我们要知道什么是小程序。市面上有很多小程序,包括微信小程序、百度小程序、支付宝小程序、字节跳动小程序等,但都大同小异。相比传统APP,小程序无需安装、无需卸载,运行在微信、百度、支付宝等大型APP载体上。虽然各个小程序都大同小异,但都定义了自己的开发语言和规范,这也给开发者带来了不少麻烦。

小程序是介于网页应用与原生应用之间的产物;

小程序与APP的关系

我原本以为APP就是用app加载一个h5文件,然后通过js桥接跟原生通信,这样js调用h5方法,h5方法调用原生方法。弥补h5不能拍照、打电话等缺点。但是这样产生的h5会出现短暂白屏的情况,体验达不到原生效果(提供简单demo)。后来接触了小程序,感觉小程序的体验跟原生没太大区别,可以说非专业人士基本看不出来区别。原本以为小程序跟RN、weex一样都是原生的效果图,后来才知道也是效果图,原来也是app,那么它的体验是怎么样的呢?都是效果图,为什么小程序的体验比普通的h5好呢?这让我很感兴趣,于是开始深入了解小程序。

初步了解用h5做APP和小程序的区别:

相同点:

1. 全部都是渲染

2.两个js都通过桥接和通信

3. 都可以调用原生组件

4. 可以将资源文件下载到本地并加载进行渲染

不同之处:

1.HTML有DOM操作,而小程序是虚拟DOM,会屏蔽直接DOM操作

2. 小程序有一个服务层,负责处理业务逻辑和数据处理

3.小程序页面拥有原生页面的生命周期管理

4. 小程序标签和栏为原生控件

5. 小程序网页不是h5

6. 小程序基于微信,跨平台

小程序原则

我们以微信小程序为例,进一步讲解小程序的原理。

我们都知道微信小程序有自己的开发语言,以wx开头的方法有很多。那么转换成微信小程序能识别的语言是什么呢?微信开发工具开发完成提交审核后,审核通过后发送到微信端的到底是一个什么样的文件呢?带着这些问题,我查阅了很多资料。小程序的技术架构非常清晰易懂,JS负责业务逻辑的实现,而展现层则是通过WXML和WXSS来实现的。前者其实是微信定义的模板语言,后者和CSS类似,但是语法毕竟是自定义的,所以要么在发送前进行编译,要么在渲染时转换成微信可识别的语法。我们发现微信对这两个节点都做了处理,当我们拿到发送到微信端的格式的小程序包时,解包之后就是js和html,不再是我们开发的WXML和WXSS格式了。 但是这些html文件直接用浏览器打开是空白的,是的,里面是空的,内容是在渲染的时候动态添加的。

1.小程序是如何编译的?

我们先来看打包编译层,微信是干什么的呢?微信的打包编译都是在服务端做的,我找了一个类似的,在这里描述一下,可能不准确,只能作为参考。

其他步骤应该都不难理解,我觉得最难的就是wxml和wxss生成对应的页面文件,这个页面可不是普通的html文件,前面也说了它的body是空的。如果你有安装微信的开发工具,可以找找有没有wcc和wcsc两个小工具,wxss是转换成css,wxml是转换成css。其实命令可以得到小程序里的构建脚本wcc和wcsc,以及各个版本小程序的执行SDK***。这个SDK也可以用-app-解包,解包之后里面有.js和.js代码。

根据//***// /微信网页开发者工具/路径,找到微信开发者工具目录,查看工具集成的核心类,可以看到我们熟悉且非常重要的.js、.js2文件也在其中,但代码经过加密混淆,可读性不高。

2. 如何发送和解析编译后的小程序包

看下面这张图,这是微信发的一个文件格式(每个小程序都是这样的一个包),这个文件可以从越狱或者root过的安卓手机上获取,有的人抓包拿到了下载链接和包,解压之后就是这个目录格式了。这里简单解释一下每个文件的作用和出处:

app-.json:小程序整体配置文件,主要包括page、、、、、ext等的json文件。

“页”: {

“/shop/.html”:{

":{

“H”:

},

“//.html”:{

":{

“xt”:“产品详情”,

“H”:

},

“///列表.html”:{

":{

“xt”:“地址列表”,

“H”: ,

“”:“”

},

},

“”:“/shop/.html”,

““: [“/店铺/”, ”///”,…],

":{

":{

"": "",

“”:“#”,

“xt”:“”,

“啦”:“”

},

“分机”:{

“api”:{

},

“形式”: {

},

“名称”:“商店”

},

页面开发流程_小程序开发页面展示_开发界面

“”:“########”

页面节点:管理各个页面的整体设置,比如原生的标题样式,是否需要下拉刷新等。可以说这些设置都是原生的设置。没错,每一个小程序页面都有对应的原生页面,所以可以把原生页面的生命周期封装起来暴露给小程序页面,包括原生和下拉刷新的控件。这也是为什么如果小程序挡住了内置的调整,就要自己重新做下拉刷新自定义,不再是原生的了。默认的下拉刷新效果就是原生下的整个动画效果,这显然不能满足我们的需求。

:此节点比较简单,小程序入口页面的配置

Node:页面路径数组,对应小程序源码中app.json文件中的节点

Node:全局设置及全局变量等;整个小程序所有私有页面均生效,即各个没有自己单独设置的页面,都直接使用这个全局设置的效果。

ext,node:对应ext.json文件,第三方平台部署小程序才需要。

Node:配置原生样式、页面路径、图标等。

app-.js文件:这个是小程序非常重要的文件,是小程序体验非常重要的一部分。从下图抓取的代码片段不难看出,这个文件是小程序中所有js文件的集合。通过=true标记起始页来进行路由。

var = || {};**

var = || “”;

var = || “”;

var = || {};

var = || {};

var = || {};

var =||""; **

var = || (){};

var = || (){};

var = || (){};

var = || (){};

define("app.js", function(require, module, exports, window,document,frames,self,location,navigator,localStorage,history,Caches,screen,alert,confirm,prompt,XMLHttpRequest,WebSocket,Reporter,webkit,WeixinJSCore){

“使用 ”;App({:(){var e=this,o=wx.(“logs”)||[];o.(Date.now()),wx.(“logs”,o),wx.({:(e){}}),wx.({:(o){o.[“。”]&&wx.({:(o){e..=o.,ek&&e.k(o)}})}})},:{:“ ”,text:“ ”}});

**});("app.js");

='//'; = true;("//.js", (, , , ,,,self,,,,,,,,,,,,,,){

“使用”;页面({数据:{},:(n){},:(){},:(){},:(){},:(){},:(){},:(){},:(){},:(){},:(){}});

});(“//.js”);****

3. 如何渲染小程序

小程序除了各个页面的js之外,在这个文件中还包含了一个app.js文件,里面包含了小程序整个生命周期管理逻辑的js文件内容。在微信端,小程序SDK会有一个单独的app-.js文件来加载作为小程序的服务层,负责各个页面的逻辑处理,并且这个服务在整个小程序的生命周期中都是一直存在的。各个页面的js文件已经被压缩在这个文件里,在小程序服务启动的时候就加载到内存中,所以在点击一个按钮做逻辑交互的时候体验才会如此之快。

App(逻辑层)主要由app-.js文件和微信app内集成的.js组成。比如一个页面加载需要网络请求,逻辑层处理请求参数后交给进行请求,将请求的数据返回给App(逻辑层)进行数据处理,最后通过将处理好的数据交给view(视图层)进行渲染。逻辑层和视图层之间没有直接的交互,逻辑服务层和视图层也不在同一个线程中,两者只能通过进行通信。

文件夹没什么特别的,跟你开发微信小程序的目录是一样的,里面装的是你的页面和组件的HTML文件。但值得一提的是,HTML文件中的内容很少,并不是一个完整的页面,可以说这个页面的样式和静态内容都不在这个HTML里面,里面装的是这个页面的CSS,路由路径和加载入口方法的调用:$gwx('.////.wxml')。大家可以看一下我的页面代码,会更清楚一些。

/* //.wxss */

{

-: 红色的;

:100%;

:;

: 柔性;

-:;

-:;

这是一个非常简单的小程序页面代码,那么编译出来的HTML页面代码是什么样的呢?下面我就给大家展示一下。

你发现了什么?" "页面的关键内容没了,那么它是怎么渲染出来的?懂js的人大概都能轻易的看出这个页面的入口方法:$gwx没错,这个方法是一个很重要的方法。那么这个方法在哪呢?" "页面的关键元素在哪呢?肯定是跟这个资源包一起分发的。没错,所有的页面标签和元素内容都在page-.html文件中。也就是wxml文件的代码被编译压缩到了page-.html文件中,而对应页面的html文件中只包含了对应的wxss文件代码和入口js代码。入口方法是由原生app调用js""事件来触发的。对于原生sdk,后面可以以OC为例贴出对应的代码,然后再进行扩展。

页面-.html文件:这个文件应该是小包里最大的文件了,就不方便贴出里面所有的代码了,我简单介绍一下它的组成和作用。第一部分:模板View层是各个页面共有的,如何把vdom渲染到里面。$gwx方法就在这个模板里,一个页面的入口。

我们先来看看刚才 HTML 页面中关键的元素“ ”消失到哪里去了?每个元素都转化成一个 Z 型数组,每个页面都是这样的代码块。混淆和压缩使得阅读起来比较困难,但是如果你以为看完这个文件就大功告成了,那你就错了。View 层除了这些 HTML 文件之外,还需要一个很重要的文件,就是微信应用包中的 .js 文件。 层中也有一个 .js 文件,与其配合,实现原生交互的效果。

与原生代码的交互属于小程序框架的范畴,所以肯定不会包含在小程序包中。除了原生SDK代码外,还有两个非常重要的js文件,就是上面提到的.js文件和文件。接下来我们来简单了解一下:

为了方便理解,我整理了一些js和的API,包括app(小程序)层面,页面层面,以及组件层面,可以看出js和交互非常频繁,可以说每个操作都需要View层的js调用的桥梁,如果需要处理,就先处理完再到app(逻辑)层,js通知逻辑层处理相应逻辑,再将处理结果返回给。

小程序在App中执行时,被分成View//三个不同的模块,每个模块都有各自的功能。View和View都是在App中执行的,互相之间不能调用,也不直接操作DOM,它们通过View层进行通信。而View和View之间互相调用。小程序依赖于底层API接口的调用,因此在小程序中开发时,开发者不需要过多考虑iOS和的实现差异,可以专注于上层视图层和逻辑层的开发。

启动小程序服务,根据基本信息判断小程序是否已经下载到本地电脑,若没有则下载解压加载配置信息,然后进入。其实分为几个部分:一个是小程序层级管理,一个是单个小程序的管理,具体细节可以通过下面的类图更直观。

下图是小程序启动的时候会去CDN和服务器验证并下载资源,这个是小程序启动慢的主要原因,需要一些时间来初始化小程序本地服务。

4. 小程序的生命周期

小程序的生命周期可以分为两部分来理解:应用生命周期(左侧蓝色部分)和页面生命周期(右侧绿色部分)。

应用的生命周期如下: 1. 用户首次打开小程序,触发该方法(全局只触发一次)。 2. 小程序初始化完成后,触发该方法,监控小程序展示。 3. 小程序从前台转到后台,触发该方法。 4. 小程序从后台转到前台,触发该方法。 5. 小程序在后台运行一定时间或者占用系统资源过多,会被销毁。

页面生命周期是这样的这样一个过程:1.小程序注册后,页面加载完毕,触发该方法。2.页面加载完毕后,触发该方法,显示页面。3.页面首次显示时,会触发该方法,渲染页面元素和样式。一个页面只会调用一次。4.小程序在后台运行或者跳转到其他页面时,会触发该方法。5.小程序从后台进入前台或者重新进入页面时,会触发该方法。6.使用重定向方法wx.()或者关闭当前页面返回上一个页面wx.()时,会触发该方法。同时,应用的生命周期会影响页面的生命周期。

使用 Page 实例的页面的生命周期

从上图可以看出,小程序由两个大线程组成:负责界面的视图线程(view)和负责数据和服务处理的服务线程(),两个线程共同协作完成小程序页面生命周期的调用。

视图线程主要有四种状态:

服务线程的五种状态:

小程序在APP中的应用场景

说了这么多技术理论,我们来谈谈如何将小程序应用到项目中。整个项目都用小程序是不现实的,毕竟小程序的定义是轻量级的,比如IM、消息肯定比小程序更适合原生应用,所以小程序和原生应用的混合开发是必不可少的。为什么要做混合开发还有一个重要的原因,你的应用并不是一个新项目,而是一个已有的原生应用,用小程序重新做一遍是不现实的,所以混合开发是最好的选择。我这里做的混合开发不是技术层面的,我们都知道小程序非常原生,沟通非常频繁,需要原生应用提供各种能力,才能达到近原生的体验,所以本身就是混合的。我这里说的混合开发是指业务层面的混合开发,这打破了我们之前对小程序的理解,无论是百度小程序还是微信小程序,它们都是在各自的生态中运行的独立应用。 比如一个商城小程序,不会有一部分页面是原生的,一部分页面是小程序的,而且只有一个入口和一个出口。我们想用小程序来开发APP,我们的APP有自己的要求,我们要让小程序看上去像原生的页面,对用户来说,它还是一个APP,没有哪个页面是原生的,哪个页面不是原生的。所以一切从技术角度来讲,就是小程序和原生混合开发的商业APP。你可以把它看成是在你的APP里面嵌入h5的开发模式,只不过小程序页面比一般的h5页面交互体验更好一些。

我可以从原生页面跳转到小程序的任意页面,如果有需要,我也可以从小程序页面跳转到原生页面。所以进入小程序页面时无法启动小程序服务,返回原生页面时也无法销毁小程序服务,你必须根据你的业务场景来调用控件。

以上是我个人对小程序及APP开发的一些看法,期待与业界同仁一起探讨。大家有什么看法呢?欢迎评论交流。

最后,我要感谢所有行业领袖的贡献。以下是我的参考:

分享