评论

一场比赛,一窥小程序的有限与无限

华南赛区二等奖「Resser 阅见」小程序开发经验分享

本文参加2019年「大赛文章征集」征文活动

大家好,我是华南赛区二等奖「Resser 阅见」小程序的开发团队DeveSA的队长。继上一篇高校微信小程序大赛经验分享杂谈流水账般介绍小程序的开发流程,这次我们来谈谈更Deep一点的——小程序的有限与无限。

「有限」和「无限」乍一看是不是很玄乎?让我稍稍剧透一下,这里的「有限」指的是小程序开发和运营上受到的限制,而「无限」则是小程序与生俱来的裂变能力和发展前景。本文的目的不只是简单地罗列这些Pros&Cons,也会根据在比赛中汲取到的经验分享给大家如何越过这些Cons并利用好Pros。

技术层面

wx.request

我相信每一个开发过小程序的developer,都记得大明湖畔的wx.request。曾几何时,比赛群里都是大家讨论如何在ddl前搞好备案,又或是ddl前一天匆匆忙忙设置好调试模式。

wx.request是微信提供的网络请求接口,限制诸多,有:

  • 只支持HTTPS协议
  • 不能使用IP地址或localhost
  • 不支持8080以外端口
  • 请求的域名必须经过ICP备案
  • 用来鉴权的api.weixin.qq.com不能配置为服务器域名
  • Header中不能设置User-Agent
  • 20个域名限制

而我们开发的「阅见」本质上是RSS阅读器,请求的feed链接都是用户自定义的外链,这些外链有HTTP的,也有没有备案的,数量更是无限的。这不就完美和wx.request的限制撞车了吗?

在这些限制下,很多同学第一反应是匆忙给自己的服务器上证书、上备案,却也不免遇上使用的第三方开放API(如http://api.github.com)没上备案的问题。这就引出了更高阶的解决方法——在自己已备案的域名上设置tracker域名转发。然而,还有一种更优雅的方法——云函数。
也就是,原本从小程序到目标服务器的过程(上图)中间加入了云函数(下图)。


借助于云函数与小程序得天独厚的血缘关系,小程序配置和调用云函数都十分方便。

云函数使用原生的request对传入的网址进行请求:

const request = require('request');
exports.main = (event, context) => {
  return new Promise((resolve, reject) => {
    request(event.options, (error, res, body) => {
      if (error) return reject(error);
      resolve(res);
    })
  });
}

小程序端则将原本的wx.request封装一下,代码有点长,只给个思路:

wx.vrequest = function (options) {
  //将options转发到params,过程省略
  return new Promise((RES, REJ) => {
    wx.cloud.callFunction({ //请求云函数
      name: 'v-request',
      data: {
        options: params
      },
      success: res => {    
          const { result }  = res;
          options.success && options.success(result);
          RES(result); 
        },
        fail: err => {
          //错误回调
          REJ(err);
        },
      complete: options.complete
    })
  })
}

具体部署可以参考Github上guren-cloud/v-request

WXML与富文本解析

解决了wx.request的问题,「阅见」遇到的第二个问题就是很多网站不支持RSS全文输出,因此我们计划让「阅见」能得到文章原文的HTML内容输出,再经过富文本渲染,呈现在小程序上。

小程序采用WXML,微信设计的一套标签语言,然而,网页上的富文本都是通过HTML呈现出来的,这样的话,当小程序想显示网页内容时,只能调用web-view了,而web-view不支持个人类型的小程序…… Butttt,多亏了小程序良好的生态环境,有很多开发者为小程序编写插件和库,其中,有关富文本渲染的就有wxParseTowxml。其中wxParse已经两年没有更新了,虽然也有各路大神fork改良,但由于RSS获取到的文章千差万别,支持性不是很好(比如代码显示以及ruby标签等)。这里我强烈推荐Towxml,除了这个渲染库比较新之外,Towxml还有许多优良特性,比如,官方号称的“极致的中文排版优化”。

Thanks to Towxml,在「阅见」中,用户可以看到排版优良的订阅内容,甚至还能看视频哦。

除了Towxml,「阅见」还借助了URL2Article提供的API提取正文内容,其能精准识别网页的正文部分,提取的内容不含广告导航等非正文内容。

资源占用

说起小程序,你能想到最合适的形容词是什么?对我来说,就是「小」,这个「小」不只提现在小程序「触手可及、用完即走」的轻量,还有对开发者实在的限制——打包体积不能超过2M,本地缓存上限10M。

这对于在大内存时代动辄上百兆代码的coder们来说,无疑是极大的限制。Butttt,在实际编写小程序时,只要有良好的编程习惯,这2M和10M是完全够用的,因为代码包经过了GZIP压缩后压缩率可以达到80%。

话虽如此,在「阅见」中,主要操作都是在小程序端完成的,所以相应的逻辑代码很多,在开发后期我们也的确遇到了代码包超过2M的情况。下面给一些减小代码包的体积的Tips:

  1. 小程序中只保存图标需要的图片文件,除tabbar外图标都使用·svg矢量格式,不仅体积相比.png等传统点阵格式小了很多,而且也有矢量图永远高清的优点。
  2. 其他静态图片保存在服务器上或托管在图床上,七牛云就是个不错的选择,每个月还有免费的10G CDN流量,访问速度比云开发中的云储存快了不少。
  3. 删除测试使用的console.log()语句
  4. 压缩CSS代码
  5. 如果使用了第三方UI框架库,可以删除没有使用到的组件

如果以上Tips还不能解决代码包体积超过限制的问题,可以使用分包

大部分小程序都会由某几个功能组成,通常这几个功能之间是独立的,但会依赖一些公共的逻辑,并且这些功能通常会对应某几个独立的页面。那么小程序代码的打包,大可不必一定要打成一个,可以按照功能的划分,拆分成几个分包,当需要用到某个功能时,才加载这个功能对应的分包。

使用分包方式加载小程序,能使小程序承载更多的功能与服务;而对用户而言,可以获得更快的加载速度,同时在不影响启动速度前提下使用更多功能。

目前小程序分包大小有以下限制:

  • 整个小程序所有分包大小不超过 8M
  • 单个分包/主包大小不能超过 2M

除了代码包2M的限制外,别忘了还有10M的缓存限制。在刚开发小程序时,我在所有跨页面传参使用的都是wx.setStorageSyncwx.getStorageSync,不仅拖慢了程序的运行速度,还占用了宝贵了n/10M。其实,对于不需要存储在本地的跨页面传参,完全可以用app.globalData来代替:

  • app.globalData是全局变量,下次进入的时候,就要重新获取。
  • Storage是本地缓存,除非缓存被清除不需要重新获取。

运营规范

登陆

相信大家对下图的warning都不陌生:

在之前,小程序可以直接通过wx.getUserInfo调起授权弹窗,这一操作虽然很便利,但却被一些开发者滥用,有些小程序一打开就要求授权甚至不授权就不能使用。在考虑到这一点的基础上,wx.getUserInfo不再显示授权弹窗,只能用button组件的开放功能调用。引用官方的话:

用户使用登录功能就像“面基”,第一印象很重要。这几个小改动在提升小程序使用的流畅体验、避免用户对数据采集授权担忧的同时,也将驱动用户更乐意尝试使用小程序服务。

因此,好的选择是在用户第一次登陆时“微妙地提示”用户授权登陆,并且在用户未授权时也可以访问到小程序的公共内容。

模版消息

我们知道,iOS上有专门的消息推送机制,而安卓上只能通过让应用后台运行实现24小时接受消息。借助于微信的装机率和使用率,小程序不需要时刻保持后台运行也能让用户接受到消息,这靠的就是微信的模版消息功能。Butttt,为了防止此功能的滥用,模版消息的发送有两个触发条件:

  1. 支付:当用户在小程序内完成过支付行为,可允许开发者向用户在7天内推送有限条数的模板消息(1次支付可下发3条,多次支付下发条数独立,互相不影响)
  2. 提交表单:当用户在小程序内发生过提交表单行为且该表单声明为要发模板消息的,开发者需要向用户提供服务时,可允许开发者向用户在7天内推送有限条数的模板消息(1次提交表单可下发1条,多次提交下发条数独立,相互不影响)

所以开发者难免会遇到模版消息发送次数不够用的窘况。但根据第二点,小程序每获得一次formId,相当于就多了一条模版消息的「命」。简单来说,我们可以将小程序的表单组件进行封装,把用户的交互点击的bindtap事件替换为bindsubmit,乔装一下小程序中其他功能按钮,当用户点击这些按钮时,就能获取到更多的formId

⚠️ 不过即便如此,开发者也应该遵守小程序运营规范,不要滥用模板消息。

更新:根据7月25日「微信广告小程序流量主大会」消息,微信小程序将上线「一次性订阅消息」的能力,只要经用户确认,超过七天的模版消息也能送达用户。

总结

小程序脱胎于微信,出生时便自带「降低门槛、充实能力、场景流量、提高转化、交易变现」等强有力的Buff,在电商零售、政务平台多方面可以说是全面赋能,有无限的发展潜能。小程序在方便用户,降低用户使用门槛的同时,也为开发者们提供了诸多上手即用的API和组件。如此强有力的工具想要长青,自然需要在开发、运营上施加限制,此之谓「有限」,而施加限制的目的是建立友好的微信生态体系,实现用户、微信、开发者三方互利共赢,此之谓「无限」。

最后一次编辑于  2019-07-26  
点赞 12
收藏
评论

5 个评论

  • 回凉
    回凉
    2019-11-29

    跨页面传参不需要这么麻烦的操作,直接

    wx.navigateTo({
           url: `./Test?test=${JSON.stringify(params)}`
    });

    然后在Test页面的onLoad里获取params

    2019-11-29
    赞同 1
    回复
  • 2019-08-19

    ui组件库如果没有引用的话是不会被打包的,没必要删

    2019-08-19
    赞同
    回复 1
    • Gasink
      Gasink
      2019-08-19
      但是部分UI组件中有静态资源 会被打包进去
      2019-08-19
      1
      回复
  • 97
    97
    2019-07-26

    小伙子码字辛苦

    2019-07-26
    赞同
    回复
  • 吴迪
    吴迪
    2019-07-26

    做乜啊

    2019-07-26
    赞同
    回复 2
    • Gasink
      Gasink
      2019-07-26
      这是比赛征文,因为有上一篇的所以省略了背景介绍 上一篇:https://developers.weixin.qq.com/community/develop/article/doc/000484fe8684d074cdb8401f651013
      2019-07-26
      回复
    • 叶银
      叶银
      2019-08-05回复Gasink
      🙂
      2019-08-05
      回复
  • Gasink
    Gasink
    2019-07-26

    「阅见」Github开源地址:https://github.com/rhinoc/Resser

    2019-07-26
    赞同
    回复 1
    • Gasink
      Gasink
      2019-07-26
      欢迎Star
      2019-07-26
      回复
登录 后发表内容