我想独立实现一个全栈产品为什么这么难
日常生活中,我们会使用很多软件产品。在使用这些产品的时候,我们看得见的东西称为“前端界面”如一个输入框、一个按钮,点击按钮之后发生的一切看不见的东西称为“后端服务”。与之对应的创造者分别称为“前端程序员”、“后端程序员”,然而,一个完整产品的开发不仅仅是只有前端和后端,还有设计师,架构师,运维等。有没有可能这些所有的事情都一个人干呢?有可能,事实上如今就有很多的“全栈工程师”,他们身兼数职,是多面手。能独立完成一个产品的方方面面。这种人固然十分了得,他们通常具有多年的经验,涉猎广泛,是老手,也是高手,当有一个产品想法的时候,他们可以用自己的全面专业技能,尽情的发挥去实现自己的想法。所以,从某种意义上讲“全栈也是一种自由”,你可以自由的实现你的想法,这简直太美妙了!
然而,很多时候当我们有一个产品想法的时候,我们往往发现,前端写完了,后端怎么搞?数据库怎么搞?域名怎么搞?域名还要备案?应用部署怎么搞?我的买什么样的服务器啊?静态资源 CDN 怎么搞?文件上传服务器怎么搞?万一访问用户多了能撑住吗?等等……问题很多,导致你的一个个想法,都只是在脑海中昙花一现,从来都无法将她们实现,或者说你激情饱满的实现了其中自己最擅长的一部分,当碰到其他难题的时候就止步了。于是仰天长啸:我就想独立做一个完整的产品为什么这么难?年轻人,这一切都不怪你……
破局:小程序云开发
为什么使用小程序云开发来破局?
为啥是用“小程序云开发”来破局?首先,我们的目的是全栈实现一个产品。全栈可以有多种技术方案,你可用任何你能会的技能来达到全栈的目的。你可以开发安卓,IOS,或者 PC 站,然而小程序是最实际的!为啥?手机上能做的事情为啥要用 PC 版?OK,既然手机版比较好,那能不能再简单一点?能,就是小程序,不需要开发IOS,安卓两个版本。可以快速产出,快速试错。
其次,前面说到了,全栈实现一个产品并不容易,对很多人来说甚至是巨难!选择了小程序已经是比较划算的方案。而再集成云开发,全栈立马就有了。这就是为什么选择“小程序云开发”来破局。
小程序云开发是什么?
小程序云开发是什么?官方文档是这么说的:开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力。云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥。
看完上面的描述,也许你仍然无法非常清楚的知道什么是“小程序云开发”,没关系,你只需要注意加粗的部分,大概知道它“无需搭建服务器”,从传统观念将,这个似乎“毁三观”咋可能没服务器啊?是的,可以没有传统意义上的服务器,这种模式是 serveless 的。
那么,小程序云开发提供了哪些东西来破局呢?且看下面的表格:
能 力 | 作 用 | 说 明 |
---|---|---|
云函数 | 无需自建服务器 | 在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码 |
数据库 | 无需自建数据库 | 一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库 |
存储 | 无需自建存储和 CDN | 在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理 |
云调用 | 原生微信服务集成 | 基于云函数免鉴权使用小程序开放接口的能力,包括服务端调用、获取开放数据等能力 |
上面的表格中提到了“云开发”中的一些能力:“云函数”,“数据库”,“存储”,“云调用”,我们可以将这些词带入你曾经开发过的应用,看看它们分别代表了哪些部分。对于程序员来说,如果有疑问的话,没有什么是一个 helloword 解决不了的。
实战:独立开发一个简易的零售小程序
哆嗦再多,不如实战。下面我们就来使用小程序云开发实现一个简单的零售小程序。
项目构思
既然是一个零售小程序,那么我们可以思考一下零售小程序的大致业务流程,以及粗略的梳理一下,其功能点。现根据自己的想法,大致画一下草图,如果没有灵感可以参考一下别的 APP 是如何设计的。
我根据自己的想法设计之后是这样的:
功能模块:首页,商品列表页,购物车,确认订单,个人中心,个人订单,管你模块(商品添加,分类添加)其中商品需要上传图片。
梳理完功能之后,我们对于要实现的东西已经有个初步的概念了。接下来,我们需要大概画一下页面设计、及功能流转。初次设计可能没有太多经验,没关系,开始做就行了,做着做着就会想法越来越多,然后优化的越来越好。。我也是经过了多番修改调整,最终找到了一些思路。我的(拙劣)设计如下,图片如果看不清楚可复制图片链接在新窗口打开查看:
说明,以上图片是根据成品(我真的开发了一个云小程序并上线使用了)截图的,而实际我再设计的时候也是经过几番修改才最终定成这样。
同时,补充说明一下,这里前端页面使用的是 vant-weapp控件,非常好用。推荐!如果你和我一样是一个纯后端程序员,建议使用 vant-weapp 来作为 ui,非常方便。否则自己写页面样式的话可能就做不出来了。全栈不是那么好干的啊。选择自己能驾驭的,能实现最终功能,就是一个合格的全栈。
创建小程序云开发项目
我们先下载微信小程序开发工具,下载地址在这里,安装好了之后,新建项目,界面如下,APPID 需要你自己去注册一个。然后注意,选择“小程序云开发”,如下图所示:
创建好了之后,项目目录如下,先看 1 标注的地方:
如果你曾经有过小程序的开发经验,那么miniprogram
文件夹下面的结构你肯定熟悉了,miniprogram
下面的子目录分别是小程序对应的组件、图片、页面、样式以及app.js
,app.json
,sitemap.json
,其中components
下面的vant-weapp
就是上面提到的 ui 组件。
最后一个比较重要的文件夹就是cloudfunctions
,这个目录是用来存放“云函数的”,云函数就是我们的后端。每一个云函数提供一个服务。一个个的云函数组成了我们整体的后端服务。云函数可以看做是 FaaS(function as a service)。途中,2 标记的位置的“云开发”按钮,我们点进去,就可以看到“云开发的控制台”,如下图所示:
如果上图看不清楚,可以复制链接到新的浏览器窗口查看,如图,小程序云开发默认的免费套餐有一定的额度可供使用。首页便是使用统计。然后我们能看到,有“数据库”,“存储”,“云函数”。
这里的“数据库”其实就是类似于一个 MongoDB,你可以点进去创建一个个的 collection(即:关系型数据库中的table);这里的“存储”其实就是“文件夹”,我们可以通过微信提供的 api把图片上传到“存储”中;这里的“云函数”就是我们需要实现的后端业务逻辑,他就是一个个的函数(函数由我们自己写好后上传)。一般开发过程中我们在开发者工具中的cloudfunctions
目录下创建云函数(比方说是:user-add)开发完成之后在云函数目录点击右键——上传即可。然后就可以在小程序的代码中调用这个user-add
云函数。
云开发之——3 分钟实现文件上传
注意:在开始云开发之前,我们现在 小程序代码的 app.js 中加入wx.cloud.init
,如下:
App({ onLaunch: function () { if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力') } else { wx.cloud.init({ // env 参数说明: // env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源 // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 // 如不填则使用默认环境(第一个创建的环境) env: 'your-env-id', traceUser: true, }) } this.globalData = {} } })
上面的图中,我们已经看到了“商品添加”页面的效果,它需要我们输入商品名称、价格、并上传图片,然后保存。传统架构中,上传图片需要前端页面摆一个控件,然后后端提供一个 api用来接收前端传来的文件,通常来说这个后端 api 接收到图片之后,会将图片文件保存到自己的文件服务器或者是阿里云存储、或者是七牛云存储之类的。然后返回给你一个文件链接地址。非常麻烦,然而,小程序云开发上传文件超级简单,上代码:
页面代码: <van-notice-bar scrollable="false" text="发布商品" /> <van-field value="{{ productName }}" required clearable label="商品名称" placeholder="请输入商品名称" bind:change="inputName" /> <van-field value="{{ productPrice }}" required clearable label="价格" icon="question-o" bind:click-icon="onClickPhoneIcon" placeholder="请输入价格" error-message="{{phoneerr}}" border="{{ false }}" bind:change="inputPrice" /> <van-action-sheet required show="{{ showSelect }}" actions="{{ actions }}" close-on-click-overlay="true" bind:close="toggleSelect" bind:select="onSelect" cancel-text="取消" /> <van-field value="{{ productCategory }}" center readonly label="商品分类" border="{{ false }}" use-button-slot > <van-button slot="button" size="small" plain type="primary" bind:click="toggleSelect">选择分类</van-button> </van-field> <van-button class="rightside" type="default" bind:click="uploadImage" >上传商品图片</van-button> <view class="imagePreview"> <image src="{{productImg}}" /> </view> <van-submit-bar price="{{ totalShow }}" button-text="提交" bind:submit="onSubmit" tip="{{ false }}" > </van-submit-bar> <van-toast id="van-toast" /> <van-dialog id="van-dialog" />
这里有个控件,绑定了uploadImage
方法,其代码为:
uploadImage:function(){ let that = this; wx.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'], success(res) { wx.showLoading({ title: '上传中...', }) const tempFilePath = res.tempFilePaths[0] const name = Math.random() * 1000000; const cloudPath = name + tempFilePath.match(/\.[^.]+?$/)[0] wx.cloud.uploadFile({ cloudPath:cloudPath,//云存储图片名字 filePath: tempFilePath,//临时路径 success: res => { let fileID = res.fileID; that.setData({ productImg: res.fileID, }); wx.showToast({ title: '图片上传成功', }) }, fail: e =>{ wx.showToast({ title: '上传失败', }) }, complete:()=>{ wx.hideLoading(); } }); } }) }
这里,wx.chooseImage
用于调起手机选择图片(相册/相机拍照),然后wx.cloud.uploadFile
用于上传图片到上面说到的云开发能力之一的“存储”中。上传图片成功之后返回一个文件 ID,类似:
cloud://release-0kj63.7265-release-0kj63-1300431985/100477.13363146288.jpg
这个链接可以直接在小程序页面展示:
<image src="cloud://release-0kj63.7265-release-0kj63-1300431985/100477.13363146288.jpg " />
也可以通过微信 api,装换成 http 形式的图片链接。
云开发之——操作数据库,1 分钟写完保存商品到数据库的代码
上面我们实现了商品图片上传,但是,商品图片并没有保存到数据库。正常录入商品的时候,我们会填好商品名称,价格等,然后上传图片,最终点击“保存”按钮,将商品保存到数据库。传统模式下,前端仍然是需要调用一个后端接口,通过 post 提交数据,最终由后端服务(比如 java 服务)将数据保存到数据库。小程序云开发使得操作数据库十分简单,首先我们在云开发控制台创建“商品表”,即一个 collection
,取名为:products
。然后我们就可以保存数据到数据库了,代码如下:
onSubmit:function(){ // 校验代码,略 let product = {}; product.imgId = this.data.productImg; product.name= this.data.productName; product.categoryId = this.data.productCategoryId; product.price = this.data.productPrice; // 其他赋值,略 const db = wx.cloud.database(); db.collection('products').add({ data: product, success(res) { wx.showToast({ title: '保存成功', }) } }); }
以上就实现了数据入库,就这点代码,超简单,1 分钟写完,诚不欺我。其中这里的products
就是我们的“商品表”,之前说过,类似 MongoDB 数据库,这里操作的是db.collection
,这和 MongoDB 的语法差不多。
云开发之——使用云函数完成后端业务逻辑,订单创建
小程序云开发提供了几大能力:“数据库”,“存储”,“云函数”,前两项我们已经有所体会了。下面我们能创建一个云函数来实现订单创建。这里说明,云函数其实就是 一段JavaScript 代码,上传至云服务器之后,最终也是运行在 nodejs 环境的,只是这一切,我们不需要关心。我们只需要关心我们这个云函数提供的功能是什么就可以了。
创建云函数很简单,直接在开发工具中右键“新建Node.js 云函数”。然后以创建订单为例,假设我们创建一个云函数名为c-order-add
,创建好了之后,目录是这样:
云函数的主要代码在 index.js 中,其完整代码是这样:
// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ env: 'release-xxx'// your-env-id }) const db = cloud.database() // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); console.log("云函数 c-order-add : ") // 这里是一些逻辑处理... return await db.collection('uorder').add({ data: { openid: event.userInfo.openId, address: event.address, userName: event.userName, phone: event.phone, shoppingInfo: event.shoppingInfo, totlePrice: event.totlePrice, shoppingStr: event.shoppingStr, remark:event.remark, createTime: now, // ... } }); }
这个云函数写好之后,需要上传到服务器,直接在云函数目录点击右键,然后点击“上传并部署”即可,这就相当于部署好了后端服务。前端小程序页面调用的写法是这样的:
let orderData={}; orderData.userName = this.data.userName; orderData.phone = this.data.phone; orderData.address = this.data.address; // .... wx.cloud.callFunction({ // 云函数名称 name: 'c-order-add', // 传给云函数的参数 data: orderData, complete: res => { Dialog.alert({ title: '提交成功', message: '您的订单成功,即将配送,请保持手机通畅。' }).then(() => { // .... wx.redirectTo({ url: '../uorder/uorder' }); }); } })
这里,向程序前端,通过wx.cloud.callFunction
完成了对云函数的调用,也可以理解为对后端服务的调用。至此我们我们介绍完了,小程序云开发的功能。虽然,我只贴出了少量的代码,即保存商品,和提交订单。由于时间和篇幅有限,我不可能把整个完整的程序代码贴出来。但是你可以参照这个用法示例,将剩下的业务逻辑补充完整,最终完成“项目构思”一节中展示的成品截图效果。
总结及对比
这里我们可以对小程序云开发和传统模式做一个对比:
对比条目 | 传统模式 | 云开发 |
---|---|---|
是否需要后端服务 | 需要 (如一个java应用部署在 Tomcat 中) | 不需要 只需要“云函数” |
是否需要域名 | 需要 (还得在微信后台的把域名加入安全域名) | 不需要 |
是否需要购买服务器 | 需要 (你得部署后端 Java 应用,还得安装数据库) | 不需要 开通云开发之后免费套餐够用 不够的话购买套餐按调用量计费 |
是否需要懂运维 | 需要 (你得会折腾服务器,数据库之类的 还得配置好相关的用户,端口,启动服务) |
不需要 |
图片上传及 CDN | 麻烦 | 简单 |
获取微信 openID | 麻烦 | 超级简单,云函数中直接获取 |
··· |
就对比这么多吧,总之,我非常喜欢小程序云开发,小程序真的可以让你轻松干全栈。或者咱们别动不动就提“全栈”,姑且说,小程序云开发可以让你更简单、更快速、更便宜的实现你的产品落地。我自己开发的云小程序上线之后,使用了一两个月,没出现任何问题。我也不用操心服务器什么的。所以,我已经给身边很多人安利了小程序云开发了。这里我就不贴出我的小程序码了,因为已经正式给我同学的超市使用了,所以不方便让别人去产生测试数据。如果你感兴趣想看的话,可以联系我。