将小程序从云开发迁移到自建服务器

text

云开发最近开始出现大幅度调价,并配置了一个默认的最低消费:19.9 元;说起来,这个钱不多,奈何我的很多个小程序都属于用量极小,但也不能停止运转的。过去的按量付费的模式对于我这样佛系运营的小程序会比较友好。但现在这种付费模式对于我这种每个小程序量级都不大,但又多个小程序的人来说不太友好。既然我能给开发一套标准的后端,且确实觉得没必要,就花点时间从云开发迁移到自建的服务器。

评估修改工作量

在开始动手迁移的时候,先要评估一下迁移所需要的成本,我选择使用 grep 查询一下我的变更的工作量。执行如下命令,来判断我具体在哪些文件当中调用了云开发的方法,判断出具体的工作量

grep -w -c -E 'callFunction|db.collection|wx.cloud' ./**/**.wpy
Code language: PHP (php)

执行命令后,你会看到类似这样的输出,这个输出表现出了我的具体没个文件所需要的修改的量。

d2b5ca33bd970f64a6301fa75ae2eb22 6

这样对于具体要做的工作量就心里有数了。接下来要做的,无非是具体的迁移工作了。

评估云函数工作量

云开发用久了,很容易出现一些其实不再运转的函数。在这种情况下,可以不再迁移这些函数,降低自己的迁移成本。

云函数在迁移的时候,可以通过云开发提供的函数监控面来判断每个函数的调用情况,对于调用情况为 0 的函数,就可以选择性的不再提供服务了。

d2b5ca33bd970f64a6301fa75ae2eb22 8

导出数据库

从云开发迁移走的时候,我们需要迁移小程序侧的代码、云函数代码和云数据库的资源,因此,也需要将对应的数据提供导出和导入。

不过,你需要注意的是,云开发导出的 JSON 不是标准的 JSON 格式,而是 JSON Lines 的格式,在你对应的数据导入时,需要使用 package 来 parse ,而不是使用标准的方式来进行 Parse。

d2b5ca33bd970f64a6301fa75ae2eb22 7

修改代码

当上面的事情做完了,接下来要做的,就是具体的写代码来进行迁移了,记得迁移服务端 & 客户端两侧的代码~。

WePy 整合云开发

由于工作上的原因,有需求要使用 WePy,刚好,有了云开发的契机,就决定研究一下。

初试 WePY

想要做云开发和 WePY,首先要先熟悉 WePY。 WePY 其实之前就听说过,不过自己一直没有使用,更多还是习惯用小程序原生写法来进行开发。

后续,也用过一些其他的框架,比如 MinUI 。

和 MinUI 相比,WePY 给我来说最大的感受是提供了 promise 的支持和 async/await 的支持,这个支持可以极大的改善 JavaScript 编程时遇到的 Callback Hell 的问题,可以让我们更加愉悦的开发。

此外,我比较看重的特性是支持外部的 NPM 包,支持 NPM 包意味着可以更好的使用 JavaScript 原本的工程化的产品,也是大大提升生产力的特性。不过,相比于 Promise 的支持和 async/await 的支持,这个如今已经被微信小程序官方团队所支持的 npm 也显得不那么重要了。

做一个 WePY 的 tempalte 吧!

在看文档时注意到,WePY 是使用 wepy init 来进行初始化的,而且可以使用 wepy list 来查看项目的模板。发现了其中有一个基于 ZanUI 的模板。

由于 ZanUI 及更名后的 VantUI 我都比较熟悉,所以从他下手,去研究一下如何制作 WePY 的模板。

复制 repo名/模板名,并在前面加上 github 的域名,就找到了对应的 repo 。

简单的看了一下项目的文件,发现其中并没有什么特殊的,需要指明初始化内容的文件,所以猜测大概率是不需要进行单独的配置的。

这方面 WePY 的文档做的不是很好,我在文档中并没有找到相关的说明。如果可以的话,希望开发者可以加一个功能,比如加上一个 .wepy-template ,可以在里面加入一些交互式的问题,从而来让用户设置一些内容。

在确定了模板其实并不困难以后,我就开始做自己的云开发模板了。

如何做一个模板

做一个模板只需要三步

  1. 下载官方的 empty 模板
  2. 加入你自己的代码
  3. 上传到 Github

说起来简单,不过,在实际制作时,还是应当注意一些问题:

  1. 初始化 Empty 模板后,尽快使用 git init 来初始化版本控制。这是因为云开发是与小程序的 AppID 进行绑定的,如果前期没有做好控制,容易出现后续将 AppID 加入了版本追踪。所以在一开始,我就将项目进行了初始化,方便后续的回溯。
  2. 上传到 Github 时,应当注意配置 Readme,在我之前的文章中,曾经提到过我们应当尽可能的交付一些产品给世界,好让世界根绝我们所交付的产品进行估值。特别是对于模板类型的 repo ,更是需要一个非常好的 Readme ,来引导别人去使用自己的模板
  3. 制作完成模板后,记得自己使用 wepy init 命令将整个过程完整的走一遍。确保你的模板是可用的。

在使用 WePY 过程中遇到的一些问题

CloudFunctionRoot 的设定问题

在做第一个版本的时候,我是将云函数的目录放在 src 目录下,后续,在运行时发现, WePY 会自动编译云函数的目录,导致出错。不得已,我将云函数的目录放置在了项目的根目录。

当时在研究这部分时,我试图去寻找 wepy.config.js文件的配置说明,希望找到一个 exclude 配置项目,来忽略一部分目录,可惜,我并没有找到。

WePY 下的一些定义问题

在使用原生写法的时候,我常常会在 Page({}) 函数外部放上一些引用。比如这样

const database = wx.cloud.database()
const storeCollection = database.collection('store')
Page({
    onReady():function(){
        // some code
    }
})

在 WePY 中我试图将代码放在 Page 实例的内部,不过会导致报错,因此,我不得不废弃这样的写法,改用 constructor 来实现。

 export default class Index extends wepy.page {
    constructor () {
      super()
      this.db = wx.cloud.database()
    }
    onLoad() {
      console.log('onLoad')
      console.log(this.db)
    }
}

对 getApp 报错

在 WePY 中,由于传承了 Vue 的思想,并没有提供对 getApp的 hack ,不过在实际的测试过程中,发现 getApp() 依然可用。

如果不引入 Redux 之类的状态管理工具的情况下,getApp() 的单例模式作为一个全局的 Bus 来进行数据的传递还是非常方便的。

关于 WePY 的其他

总的来说, WePY 是一个值得尝试的框架,单纯 Async/Await 的引入,可以让你的代码变得更加简洁易懂。特别是如果你的项目需要长期运转的情况下,整洁的代码会帮助你的项目成功。

此外,如果你很习惯于 Vue 的写法,那么 WePY 不容错过,computed 属性还是非常实用的。