我是怎么开发 轻巧日记 这款小程序的


开发

小程序的开发对于大部分的开发者还是相对简单的,如果有一点前端的开发经验,可以很快的开发出一个简单的小程序应用. 本文我想简单分享一下我是怎么开发 轻巧日记 这款小程序的,Moodz, 是轻巧日记最开始的项目名称.


框架


我在 Moodz项目中没有使用任何框架, 而我们的 Udacity 官方小程序使用的, 市面上有不少针对微信小程序的开发框架架,他们主要解决两个问题:


  1. 开发体验和多端代码共用.
  2. 开发者希望可以像开发 React 或者 Vue 的项目一样开发小程序.

我个人是更倾向于不依赖框架来进行小程序的开发的,一方面是 Moods 是一个功能较为简单的项目,UI 上没有不需要特别复杂的组件结构,数据上也不太需要太复杂的状态管理,所以使用原生框架就够了。使用第三方框架,一方面是需要额外的时间去熟悉他们的文档,开发模式等,而且也担心他们能否保持更新,同步小程序的接口更新等问题。


后端

Moodz 完全使用微信提供的小程序云开发能力来进行 API 的开发。用到小程序的云函数在进行计算功能,用小程序的云数据库来进行数据存储功能。


小程序的云函数和我们常用的 AWS 的 lambda 区别差不多,就是定于一个函数,然后在小程序中直接调用该函数。而通过 wx-server-sdk我们又可以在云函数内部去调用云数据库和云存储服务。


const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {
  return db.collection('todos').get()
}


当然还有一个更有用的功能,那就是使用云函数来获取用户相关信息: OPENID, APPID, UNIONID.


const cloud = require('wx-server-sdk')
exports.main = (event, context) => {
  const { OPENID, APPID, UNIONID } = cloud.getWXContext() 

  return {
    OPENID,
    APPID,
    UNIONID,
  }
}


云数据库和 MongoDB 非常的像,API 也很简单,通过它的 command也可以实现较为复杂的查询。当然如果你发现自己需要很复杂的查询语句的时候,也到了该重构你业务逻辑的时候了。


云存储的 API 很简单,使用起来也很方便. 而且还有临时链接的功能,只提供了下面四个 API:


uploadFile	上传文件
downloadFile	下载文件
deleteFile	删除文件
getTempFileURL	换取临时链接
所以想实现复杂的业务逻辑,需要更多的业务代码来支持。

测试

工具 Jest
测试小程序和我们平常的前端应用有一些区别, 比如测试 React 应用,我们可以使用 Enzyme, 它提供的 shadow, mount 以及 render 可以大大减轻我们的测试劳动力。而对于小程序来说,我们程序的代码逻辑主要运行在 App, Page 这两种小程序全局的作用域中,所以测试的第一步就是如何 mock AppPage. 和其他使用 Jest 作为测试工具的项目一样, 我们习惯在 setupFiles文件中进行 global 对象的构造. 所以你需要在你的 jest.config.json 中添加下面一行:
"setupFiles": ["<rootDir>/test/jest.setup.js"]

然后在 jest.setup.js 中进行 wx, App, Page 等微信小程序相关的对象和函数进行 mock. 所以只要:
global.wx = {
	cloud: {
		init: jest.fn(),
	},
	....
}


可以往 global.wx 塞进去任何我们希望 wx拥有的属性, 当然其实我们主要是为了 mock 小程序中 wx这种对象的行为。同理,对于 AppPage 也一样, 不过他们特殊的是,AppPagefunction, 这两个函数的输入是: 初始数据,页面或者App的生命周期函数,还是就是我们的各种代码逻辑了。


const noop = () => {};
const isFn = fn => typeof fn === 'function';

let wId = 0;
global.Page = ({ data, ...rest }) => {
  const page = {
    data,
    setData: jest.fn(function (newData, cb) {
      this.data = {
        ...this.data,
        ...newData,
      };

      if (isFn(cb)) cb();
    }),
    onLoad: noop,
    onReady: noop,
    onUnLoad: noop,
    __wxWebviewId__: wId++,
    ...rest,
  };
  global.wxPageInstance = page;
  return page;
};


而对于 App 我不只是要 mock 它本身,如果你在函数中使用到 getApp 这个全局函数,也需要根据实际情况 mock出来, 比如:


global.App = ({ ...rest }) => {
  const app = {
    onLaunch: noop,
    ...rest,
  };
  global.wxApp = app;
  return app;
};

global.getApp = () => ({
  track: jest.fn(),
  toast: jest.fn(),
});


监控

如果完全使用小程序的云开发组件 (云函数,云数据,云存储) 来作为小程序的后端,那么监控就不太需要我们操心了,因为小程序后台已经有不错的日志监控能力


在一般的网站前端,我们可以选择 Sentry , Airbrake 等 Error trace 服务。而小程序的前端监控方面,目前没有发现特别好的方案. 一般我们会这么做, 在 ApponError中去上报错误信息. 具体是在我们的 App.js中加入:


 onError(msg) {
    wx.reportAnalytics('onerror', { ctx: msg });
  },


不过我们需要在我们的小程序后台进行事件的配置,可以参考这里 .


宣传

嗯,顺便宣传一下我热乎乎开发的小程序 Moods, 打开微信扫码适用一下吧。

图片