浅析微信小程序技术架构

周末万里虎抽空体验了下微信小程序的DEMO,对小程序的开发有了一个基础的了解与认识,今天就来和大家分享一下我对小程序的看法。

从官方DEMO来看,小程序在技术架构上非常清晰易懂。JS负责业务逻辑的实现,而表现层则WXML和WXSS来共同实现,前者其实就是一种微信定义的模板语言,而后者类似CSS。所以对于擅长前端开发,或者WEB开发的广大开发者而已,小程序的开发可谓降低了不少门槛。

从上面的微信小程序架构图上可以清晰的看出,小程序借助的是JSBridge实现了对底层API接口的调用,所以在小程序里面开发,开发者不用太多去考虑IOS,安卓的实现差异的问题,安心在上层的视图层和逻辑层进行开发即可。

当我们在启动小程序的时候,你会发现首次启动的时候,会有点延迟的想象,这里其实是小程序正在从CDN和WEB服务器上下载资源导致的延迟。我个人感觉这个是目前小程序体验上的一点小缺憾,有延迟加载的感觉。

关于小程序的生命周期,可以分为两个部分来理解:应用生命周期(左侧蓝色部分)和页面生命周期(右侧绿色部分)。其中应用的生命周期是这样一个流程:1、用户首次打开小程序,触发 onLaunch(全局只触发一次)。2、小程序初始化完成后,触发onShow方法,监听小程序显示。3、小程序从前台进入后台,触发 onHide方法。4、小程序从后台进入前台显示,触发 onShow方法。5、小程序后台运行一定时间,或系统资源占用过高,会被销毁。 页面生命周期是这样的一个流程:1、小程序注册完成后,加载页面,触发onLoad方法。2、页面载入后触发onShow方法,显示页面。3、首次显示页面,会触发onReady方法,渲染页面元素和样式,一个页面只会调用一次。4、当小程序后台运行或跳转到其他页面时,触发onHide方法。5、当小程序有后台进入到前台运行或重新进入页面时,触发onShow方法。6、当使用重定向方法wx.redirectTo(OBJECT)或关闭当前页返回上一页wx.navigateBack(),触发onUnload。同时,应用生命周期会影响到页面生命周期。

综上来看,小程序的技术架构上的清晰明了,相比沉重的原生APP开发而已要好理解的多。而近期小程序官方逐步的释放小程序的一些入口,由此可见小程序也将慢慢的得到微信官方更大的流量支持。万里虎个人还是非常看好小程序的未来,简单、高效、方便、快捷的用户体验,这些都符合一个好程序的特质。小程序也许会在不久的将来成为下一个金矿,吸引更多开发者涌入。

三步瘦身法 司马亮教你为app“塑形”

相信很多同行都遇到过这个问题,那就是随着时间的推移,team合作开发的项目会因为各种原因导致我们的安装包越来越大,大到自己都不愿意去商城点击下载自己开发的这个应用了。应用跟人的身材一样,一旦“肥胖”,则下载量呈直线下滑,因此我们有必要对我们的app进行“塑形”了。

借着这个机会,我对手头的两个项目(iOS应用)进行了“瘦身”,成功瘦身1/3。其实对于一个30M左右的ipa包来说,能够成功瘦身到20M左右,已经相当不容易了。接下里描述下我是如何一步步做到的。

总体来说,应用瘦身分三个大的层次,分别是资源的优化、编译时候的优化以及深层次的可执行文件优化。

如下图所示:
总体优化逻辑

接下来详细描述这三步操作。

第一步:对于资源文件进行压缩优化

所谓对资源文件的处理,就是对项目中一些图片、音频或者视频文件的排查处理。具体方法如下:

1、搜索冗余图片资源

很多时候,我们发现尽管项目中有很多图片资源,但是有一部分图片是并没有使用的,那么如何找到这些未使用的图片呢?这里我介绍两种方法:

a、利用工具
下载一个项目工具(下载地址 http://jeffhodnett.github.io/Unused/ ),然后运行这个项目工具,在弹出的应用工具中选择我们所要排插的工程文件。即可进行自动搜索这些未经使用的文件。

b、终端命令
此种方法需要安装ack  [在终端通过:brew install ack 命令安装ack(ack用于做搜索)]  。
首先建立.sh 文件 如 unusedImage.sh(可以通过sublime Text编写)

#! /bin/bash
for i in `find . -name “*.png” -o -name “*.jpg”`; do
file=`basename -s .jpg $i | xargs basename -s .png | xargs basename -s @2x` result=`ack -i $file`
if [ -z $result ]; then
echo $i
# 如果需要,可以直接执行删除:
# rm “$i”
fi
done

然后进入你要查找的工程目录下执行 这段 shell 脚本,
sh unusedImage.sh
       运行出来的结果就是程序语言所辨别出来的一些未使用的资源图片。但是千万不要将这些图片一起删除了,因为有可能这些图片在某些地方以另外一种方式使用着。

2、排查冗余图片

123

经过运行软件,得到的冗余图片实在是多,我们接下来要做的就是用人脑对每个文件进行排除。一定要确保这个文件在应用中确实没有被使用,才能删除。对于不确定的图片素材,宁愿保留也不要轻易删除。

3、压缩优化大文件

编译项目,在我的资源中,相应路径下找到该项目文件,右键显示包内容,再对这些包内容list按照大小排序,找到其中占据比较大的一些文件。看看能否进行相应优化处理。

4、处理未使用的僵尸文件。

由于应用开发人员较多,导入进去的各种资源有可能重复,也有部分测试用的文件。那么这个时候就需要去找到这些僵尸文件,然后删除。我在整理整个项目的时候,就发现了又几个音频文件保留在项目中,而项目中没有任何地方引用。因此这个时候可以果断删除掉。

第二步:编译优化

1.编译器优化级别

Build Settings->Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest,这个选项会开启那些不增加代码大小的全部优化,并让可执行文件尽可能小。

2.去除符号信息

Strip Debug Symbols During Copy 和 Symbols Hidden by Default 在release版本应该设为yes,可以去除不必要的调试符号。Symbols Hidden by Default会把所有符号都定义成”private extern”,具体意思和作用我还不清楚,有待研究,但设了后会减小体积。这些选项目前都是XCode默认选项,但旧版XCode生成的项目可能不是,可以检查一下。

3.PrefixHeader.pch引用瘦身。

尽量避免全局引用,除非是类似网络接口类,这种基本每个类控制器都会用到的引用。我在检查中就发现,很多时候开发人员为了图方便,直接将头文件在PrefixHeader中引入,这样导致的后果就是每次编译都会将该文件引用编译。无端降低了程序运行效率。

第三步:深入分析,对于可执行文件进行压缩

其实做到上面两步,我们应用已经瘦身很多了,至少已经让我的应用安装包瘦身8M(这个数值因人而异,因项目而异),为了追求更加完美,我需要对应用进行更深入的瘦身,且看下面分解。

一、设置link map,以便本地生成记录

通过Xcode自带的link map来记录我们的可执行文件list,这里需要按照下图设置。

设置link map

点击编译,开始本地生成可执行文件记录。

二、打开沙盒路径

1、如果不知道沙盒路径,可以在自己的应用中打印其路径。

NSLog(@”沙盒路径:%@”,NSHomeDirectory());

/Users/apple/Library/Application Support/iPhone Simulator/6.1/Applications/******-****-****-****-************

打开Finder,选择前往-前往文件夹(或选择快捷键command+shift+G)输入打印出来的路径即可会得到打印结果*为字母或数字,即为沙盒的路径

2、打开Finder,选择前往并按住option键,进入资源库

找到这个linkmap 的txt文件,本次路径为:

Path: /Users/mac/Library/Developer/Xcode/DerivedData/WisdomMedical-afinsdxtbizadydfxufjuxeckkew/Build/Products/Debug-iphoneos/WisdomMedical.app/******

跋山涉水,终于找到这个文件:

可执行文件

接下来就是通过脚本文件编辑器来查看分析生成的这个文件

三、分析link map

这个LinkMap里展示了整个可执行文件的全貌,列出了编译后的每一个.o目标文件的信息(包括静态链接库.a里的),以及每一个目标文件的代码段,数据段存储详情。

(1)在LinkMap里首先列出来的是目标文件列表

列表1

前面中括号里的是这个文件的编号,后面会用到,像项目里引用到静态链接库libMobClickLibrary.a里的目标文件都会在这里列出来。

(2)在LinkMap里最后编译成的可执行文件中的偏移位置及大小

接着是一个段表,描述各个段在最后编译成的可执行文件中的偏移位置及大小,包括了代码段(__TEXT,保存程序代码段编译后的机器码)和数据段(__DATA,保存变量值)。

列表2

首列是数据在文件的偏移位置,第二列是这一段占用大小,第三列是段类型,代码段和数据段,第四列是段名称。

每一行的数据都紧跟在上一行后面,如第二行__stubs的地址0x101364528就是第一行__text的地址0×100005B80加上大小0×0135EA8,整个可执行文件大致数据分布就是这样。

这里可以清楚看到各种类型的数据在最终可执行文件里占的比例,例如__text表示编译后的程序执行语句,__data表示已初始化的全局变量和局部静态变量,__bss表示未初始化的全局变量和局部静态变量,__cstring表示代码里的字符串常量,等等。

(3)接着在LinkMap里就是按上表顺序,列出具体的按每个文件列出每个对应字段的位置和占用空间。

列表3

同样首列是数据在文件的偏移地址,第二列是占用大小,第三列是所属文件序号,对应上述Object files列表,最后是名字。

例如第二行代表了文件序号为2(反查上面就是TKPFileInfo.o)的parseWithDictionary方法占用了1000byte大小。

通过这个可以查看编译后可执行文件占据大小,便于定位和优化项目。

好了,三步到此结束。相信只要你按照着三步来进行应用项目分析,一定可以讲应用塑形成“型男”,赢的广大用户的喜爱。

谈谈APP架构选型:React Native还是HBuilder

导读:最近公司的一款新产品APP要进行研发,老大的意思想用H5来做混合APP以达到高效敏捷开发的目的。我自然就开始进行各种技术选型的调研,这里重点想说的是我最后挑选出的2款hybrid app开发技术方案:RN(react native),HBuilder。React Native是大名鼎鼎的Facebook的开源技术框架,而HBuilder是国内的H5工具开发公 司DCLOUD的产品。我自己先总结下吧:这两个技术框架在开发效率上基本上可以媲美WEB开发的速度,RN强调的是“Learn once, write anywhere”,RN不强求一份原生代码支持多个平台;而HBuilder则可以实现类似JAVA的“Write once, run anywhere”,也就是说写一份代码,即可同时发布多平台,这个效率比原生开发而言自然会double。两者的原理其实都是基于JS在做前端开发,用JS去做桥接调用原生的API,最大的优点是方便做APP的动态更新而不用频繁去发布版本,当然hybrid的这种框架也有弱势缺点,就是目前原生APP的开发生态已经趋向成熟,一些第三方库和框架不仅丰富而且稳定,所以如果改用基于JS的Hybrid app方案来做,一定要考虑APP产品是否适合用这种技术来做。

APP

下面我把一些网友对这两个框架的看法列举如下供参考:

RN -React Native部分—————————————————

React Native的核心实现:先简单说几点,详细的等回头更新。1. React Native里面没有webview,这货不是Hybrid app,里面执行JS是用的

JavascriptCore。2. 再说React Native的核心,iOS Native code提供了十来个最基本核心的类(RCTDeviceEventEmitter、RCTRenderingPerf等)、或组件(RCTView、RCTTextField、RCTTextView、RCTModalFullscreenView等),然后由React Native的JS部分,组成二十来个基本组件(Popover、Listview等),交由上层的业务方来使用(THGroupView)。3. 就如他们在宣传时所说,他们实现了一套类似css的子集,用来解决样式问题,相当复杂和强大,靠这个才能将Native的核心组件组成JS层的基本组件再组成业务端的业务组件,应该是采用facebook/css-layout · GitHub的C语言版本实现的(在ppt中我们看到了类似flex-direction: column一类的代码,这个正是css-layout支持的语法)。4. 在React Native中,写JS的工程师解决的是「将基本组件拼装成可用的React组件」的问题,写Native Code的工程师解决的是「提供核心组件,提供足够的扩展性、灵活性和性能」的问题。

 

React Native是什么?

其实这东西从Native开发来说,相当于重新发明了一个浏览器渲染引擎并且套一个React的壳,从Web开发角度来说,就是把原来React的后端换成了Native code来实现,就跟Flipboard最近搞的React Canvas 一样: Flipboard · GitHubreact-canvas
React Native的优势和劣势::

优势相对Hybird app或者Webapp:
1. 不用Webview,彻底摆脱了Webview让人不爽的交互和性能问题
2. 有较强的扩展性,这是因为Native端提供的是基本控件,JS可以自由组合使用
3. 可以直接使用Native原生的「牛逼」动画(在FB Group这个app里面,面板滑出带一点果冻弹动,面板基于某个点展开这种动画随处可见,这种动画用Native code来做小菜一碟,但是用Web来做就难上加难)。

优势相对于Native app:
1. 可以通过更新远端JS,直接更新app,不过这快成为各家大型Native app的标配了…

劣势:
1. 扩展性仍然远远不如web,也远远不如直接写Native code(这个不用废话解释了吧)
2. 从Native到Web,要做很多概念转换,势必造成双方都要妥协。比如web要用一套CSS的阉割版,Native通过css-layout拿到最终样式再转换成native原生的表达方式(比如iOS的Constraint\origin\Center等属性),再比如动画。另外,若Android和iOS都要做相同的封装,概念转换就更复杂了。

HBuilder部分————————————————————-

phonegap出的早,自然用的人多。
phonegap自己的定位是混合开发hybrid,用原生+js;
HBuilder的定位是纯js搞定一切。
5+ 和 phonegap在能力、性能、开发便利性上都优于phonegap。

先看能力:
5+ 有HTML5+和Native.js技术,HTML5+包含常用的跨平台的几百个API,能满足常规开发需求,而Native.js把40w原生api映射成js对象,这样js可以直接调原生。HTML5+和Native.js的组合形成了最强大的能力引擎。 而phonegap需要用原生工程师写原生插件并给js开发者封装接口才能实现js调原生能力,开发成本、对人的要求都不一样。

当然5+ 也支持原生插件,这点和phonegap类似。一个已经写好的原生sdk,无需使用Native.js重写,也可以通过5+ sdk来集成。详见文档中心 – 5+ App – 5+ SDK

5+的直接封装的跨平台api比较全,二维码、摇一摇、地图、微信分享、语音输入、推送这些常用api都是跨平台的,使用方便简单。详见 http://www.html5plus.org/

再看性能:

phonegap做的app,在低端Android手机上很难流畅运行,否则HTML5早就火了,原生开发早就被挤压了。Phonegap为了避免HTML5的体验不佳,采用了spa模式,但这个模式其实在低端机上也玩不转,而且代码非常复杂。
5+ App的性能更高,它的动态效果都是被我们的增强引擎处理的,通过增强的引擎,可以在低端机上流畅的运行各种动态效果,比如侧滑菜单、下拉刷新、长列表滚动,见 官网首页 – App选项卡- 性能视频

最后看开发便利性:

phonegap没有专业开发工具,语法提示、调试、打包都很麻烦。
而在HBuilder里,5+的语法api提示非常完善;
把手机通过数据线连上电脑,HBuilder可以真机运行,保存一个页面立即在手机上看到效果,Android上还可以看console.log。而用phonegap,你改完一个页面,不得不先打包,然后安装在手机上,然后发现不对,然后改下代码,然后继续打包。。。
关于打包,phonegap由adobe提供了云打包,但需要先在本机准备资源,然后提交到国外的服务器,而HBuilder是一键打包,更加方便。当然phonegap和HBuilder都支持本地打包,那样就需要点原生开发知识了。

除了工具和runtime,还有mui框架

phonegap只是一个手机runtime,没有HBuilder工具,更没有Mui框架。
mui是目前最接近原生App的HTML5框架,它的体验比jqm、bootstrap等框架更接近原生,它的性能远高于jqm、bootstrap、Ionic、framework7等框架。
这种性能差别原因有2,一方面是设计思路不同,mui坚持用原生js做,不依赖jquery或angularjs,因为框架的依赖越多,App性能越差;另一方面是因为mui调用了5+的底层原生加速,这比不带原生加速的框架更快。
mui详见:http://dcloudio.github.io/mui/

当然phonegap有一个优势,就是能支持windows phone、blackberry,这方面5+确实没有支持。

 

优势:Dcloud的其他服务没具体用过,HBuilder用过,还是一个很不错的编辑器,整体体验还是不错,像代码提示很智能,基于Eclipse的二次开发能做出这样也挺厉害了。特别是对HTML语法支持浏览器兼容性很好。有个前端框架写CSS挺省事的。
缺点:HBuilder Size太大,而且还得联网使用,整体体验还是Eclipse风格,相比我还是推荐使用Sublime。主要是做出了的应用就是网页的体验,这个实在是不适合用来做应用。做个WebApp还行。