微信小程序:简约而不简单_点点客
点点客

科技造就移动电商先锋

股票代码:430177

微信小程序:简约而不简单

点点客 2017-08-15

大众点评+ 主要页面一览

大众点评+ 产品特性

根据小程序的开发规范,我们总结出几个影响小程序产品形态的关键特性:

Hybrid 实现,类 web 开发

代码体积不超过 1M

用户最多打开 5 层页面

不支持与 APPH5 和其他小程序间的跳转

以上特征要求我们只为用户提供核心服务,且从产品到技术,都必须围绕「简约」二字做文章。因此,结合大众点评业务场景,最终在「大众点评+」中,我们主要提供以下两种基础服务:

快速找店:通过搜索、分类列表和推荐三种形式,让用户快速找到商户,并提供包括定位、电话、点评、菜品等商户信息,帮助用户做出决策

购买团购:为用户推荐团购商品并实现交易闭环,帮助用户获得实惠

大众点评+ 开发经验谈

产品层面足够精简,我们再来看看技术层面如何做到简约。

前期技术选型

我们先看下项目之初开发同学的困惑:

小程序是个新鲜事物,参与开发的同事普遍对开发流程和运行原理知之甚少

在不知道小程序有多少坑的前提下,我们还是要保证在小程序开放前完成全部基础功能的开发,存在着不少风险

小程序的接口稳定性和丰富程度、安全性、连接速度等究竟如何

稍微了解小程序开发流程并测试接口后,我们发现在腾讯运维体系的支撑下,相关服务的稳定性和性能不用担心,但新的问题随之而来:

小程序暂不支持 npm 包管理方式、不支持类 react 组件化开发方式、不支持类 webpack 打包方式,与现阶段前端开发有较大差别,一定程度会影响开发效率

小程序实现方面,现阶段还是基于 webview,所以必须要考虑 JS CSS 的兼容性问题

对于任何新生的应用场景,开发环境、工具和框架不够完善都可以理解,但如何才能既保证开发过程的简单又提供一定的规范和工程化能力?为此,在遵从小程序基本框架的前提下,我们做了如下技术选型和简单封装:

项目区分开发目录和构建目录,在开发目录中进行开发,再通过 gulp 对开发目录进行构建(主要处理压缩等基本功能),构建目录才是小程序真正的运行代码

引入 npm packageon,解决开发依赖的管理、请求接口的版本化管理,但不使用任何 npm (只复制一份 promise 实现)

只使用 ES6 语法,配合 eslint,快速检查基本 JS 错误,(现阶段小程序报错提示不够友好,部分错误由 JS 语法错误引起)

对小程序提供的 JS-API 进行 promise 封装,代码以 promise 风格书写,以便 catch 各种运行时的错误

与此同时,我们持续关注小程序社区和论坛的动态,比如利用社区的wxparse方案处理富文本渲染的问题,但对于部分技术和框架,我们持观望态度:

各类模拟解决组件化的方案和框架(我们希望详细了解小程序的运行和构建机制,在代码逻辑相对简单的情况下,框架的封装对于我们来说弊大于利)

使用 async/await 或者 generatoer 等需要引入大量 runtime 代码的 ES6/7 语法,主要是因为 1M 代码的限制,后续会详细介绍我们在体积优化方面所做的工作(如果你只是为了学习体验小程序的开发,那就尽情使用吧)

开发过程中的「坑」

接下来进入大家更关注的环节,在开发过程中,小程序开发究竟有哪些「坑」,以及我们如何应对?其实作为内测用户,在小程序开发的初期,确实遇到了不少坑,但这里不得不赞一下微信的同事,我们每次反馈问题都可以得到迅速响应,问题总是非常快的被解决。所以在这里我们并不打算谈论小程序有哪些 BUG ,以及怎么解决等问题,想了解的朋友可以参考推荐资料中的「微信小程序常见 FAQ」。但一些技术架构,或者产品交互上的限制,还是需要第一次开发小程序的开发者引起注意。以下仅列出我们觉得比较重要的一些问题:

平台差异

小程序会在开发者工具、iOS 设备和 Android 设备运行,不同平台可能存在实现上的差异,从而导致少许的展现不一致。不过总体来说,兼容问题比起之前的开发方式减少很多,期望小程序团队进一步做好底层兼容,为前端程序员造福。

基础架构&设计

web 接口必须是 https,且需支持 TLS 版本 1.2 以上

小程序开发采用完全的前后分离方式,web 层只负责提供 API 接口,虽然文档提到是实时更新,但发布过程中仍然存在两个版本同时被使用的问题

开发思维和技术限制

没有 BOM\DOM 操作,只能通过数据改变视图

再次强调小程序最多支持5级页面

开发代码 + 小程序编译封装的代码 = 最终的编译包 < 1M

对应的解决方案

针对上面提到的问题,我们通过自己的实践总结了一套解决方案,这里也与开发者一起分享讨论:

平台差异性

在开发过程中,我们肯定以开发者工具为主完成开发及调试,但这不代表在真机能获得与预期完全一致的展现。在过往开发 hybrid 框架的经历中,我们也总会遇到 iOSAndroidH5 表现不一致的问题,这里既涉及到底层实现的差异,也涉及到不同开发团队的沟通问题,这个问题很难一劳永逸地被完美解决。

所以针对这个问题,我们的办法是通过 log 的方式,类似 web 端日志的方式,记录关键功能的信息,再辅以常用的真机调试、抓包等调试技巧。

web 服务支持

随着苹果对 https 的推动,大众点评也完成了全站 https 化,所以在我们项目后期,这个问题自然消失了。但对于一些中小型公司或者个人开发者来说,这仍然是一个问题,这里推荐直接使用腾讯云的小程序云服务来解决。

web 接口版本化

应对思路并不复杂,可以通过 API 向前兼容,或者 API 版本化管理( API 请求中统一携带当前小程序的版本信息)方式解决,我们采用了后者。

开发思维的转变

在传统的 jquery/zepto 开发模式下,前端习惯于直接更改 DOM 内容,这种方案在大量 DOM 需要更新时就会变得非常低效,之后随着React 的推广和 DOM DIFF 技术,大家慢慢习惯于通过变动数据来实现视图的更新,不过在 react 始终保留着对 DOM 进行操作的 API。但是在小程序里面,由于 JS 代码是运行在 JSCore 中,所以不存在 DOM BOM 的概念,任何相关的操作都是无效的(你可能发现在开发者工具里面可以使用,但是在真机一定是不行的)

因此,有些常见方案的实现思路就要发生转变,包括但不局限于以下的操作:

类似微信通讯录的锚点切换(可以使用微信的 scroll-view 实现)

计算内容的高度决定截行 + 显示「展开/收起」开关

5 级页面限制

解决这个问题,其实大致有三种思路:

优化产品交互流程,尽量简化产品流程直到少于5

redirectTo 思路,在页面达到第五级之后,后续所有页面打开都通过redirectTo方式。带来的问题也显而易见,如果用户在第N个页面点击返回,他只能看到第四个页面,中间的 N-5 个页面都不见了,适用于特定场景

goBack 的思路,采用技术手段保证主流程只有5(在我们的实现中,既有把搜索功能作为页面的一个状态而非页面的方式,也有把订单提交后以 redirectTo 的方式销毁当前页面的办法),之后通过统一封装页面路由的方式,采用 getCurrentPages 接口判断当前页面是否在历史堆栈中,没有则通过 navigateTo 接口打开,有则通过 goBack 的方式返回,在页面侧 onShow 事件中去读取最新的参数信息,完成页面的更新动作

优化代码体积

最后,我们单独来聊一聊代码体积优化的问题。

为什么要优化体积?

虽然现阶段大众点评+仅提供了找店和团购两个主要功能,但 1M 的代码量毕竟太小,为了在 1M 的体积下把更多的功能和更好的体验带给用户,并未为以后的扩展预留足够的空间,这就要求我们在代码的体积控制上必须「斤斤计较」。

小程序体积是如何计算的?

小程序会把我们项目的 jsonwxmlwxssjs 全部转化为 js,合并成一个文件上传到微信云服务器。当用户第一次打开小程序时再从服务中下载并解析。以我们的项目为例,通过工具的压缩和统计,在我们计算出项目体积达到了~370K,经过微信编译上传,在手机端预览下载时,下载的文件达到了~540K,这正是开发者工具显示告诉我们的编译包大小。

如何优化?

编译层面:在编译包和开发包直接存在了~170K 的差距,开发者是否有办法通过代码写法进行优化,还需要我们去深入的了解。

构建层面:自己对 JSWXSSWXML 进行压缩,通过我们的项目测试,在使用微信默认的代码压缩上传的情况下,我们的项目体积增大了~100K

接口层面:web API 返回的数据尽量是最小的,且最好是可以直接展示的,也就是说需要在我们的 web 接入层要完成对数据的处理工作,比如时间、距离的展示等等

开发层面:

wxss 尽可能的使用 import 复用,且减少样式的命名长度,背景图片统一以 url 的方式使用,因为样式的压缩只能是去掉空格,在页面展示复杂的情况下,wxss 可能会占用比 JS 更多的体积(在微信开发者工具 beta 版上已经修复了因为 import 的使用导致引入冗余编译文件,增大编译包的问题);

js 功能尽可能以模块化的方式,如果你的小程序需要多个开发团队参与,主要负责团队需要设计提供统一的前端公共服务;

精简 wxml,我们发现当 wxml 被编译成 js 后会占用非常大的体积(减少一个压缩后 4K wxml,可以减少编译包 9K)

免责声明

此版块内容仅用于学习、研究或欣赏。我们不保证内容的正确性。通过使用本站内容随之而来的风险与本站无关访问者可将本网站提供的内容或服务用于学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯本网站及相关权利人的合法权利。