我想独立实现一个全栈产品为什么这么难
日常生活中,我们会使用很多软件产品。在使用这些产品的时候,我们看得见的东西称为“前端界面”如一个输入框、一个按钮,点击按钮之后发生的一切看不见的东西称为“后端服务”。与之对应的创造者分别称为“前端程序员”、“后端程序员”,然而,一个完整产品的开发不仅仅是只有前端和后端,还有设计师,架构师,运维等。有没有可能这些所有的事情都一个人干呢?有可能,事实上如今就有很多的“全栈工程师”,他们身兼数职,是多面手。能独立完成一个产品的方方面面。这种人固然十分了得,他们通常具有多年的经验,涉猎广泛,是老手,也是高手,当有一个产品想法的时候,他们可以用自己的全面专业技能,尽情的发挥去实现自己的想法。所以,从某种意义上讲“全栈也是一种自由”,你可以自由的实现你的想法,这简直太美妙了!
然而,很多时候当我们有一个产品想法的时候,我们往往发现,前端写完了,后端怎么搞?数据库怎么搞?域名怎么搞?域名还要备案?应用部署怎么搞?我的买什么样的服务器啊?静态资源 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
完成了对云函数的调用,也可以理解为对后端服务的调用。至此我们我们介绍完了,小程序云开发的功能。虽然,我只贴出了少量的代码,即保存商品,和提交订单。由于时间和篇幅有限,我不可能把整个完整的程序代码贴出来。但是你可以参照这个用法示例,将剩下的业务逻辑补充完整,最终完成“项目构思”一节中展示的成品截图效果。
小程序审核的一点经验
我开发的小程序审核在提交审核的时候遭遇了两次退回,第一次是因为:“小程序具备电商性质,个人小程序号不支持”。所以,我只好申请了一个企业小程序号,使用的是超市的营业执照。服务类目的选择也被打回了一次,最后选择了食品还提交了食品经营许可证。第二次打回是因为:“用户体验问题”。其实就是“授权索取”的问题,微信不让打开首页就“要求授权”,同时不能强制用户接受授权,得提供拒绝授权也能使用部分功能。
上面两条解决之后,更新新了好几版,都没有出现过被拒的情况。并且,有次我是夜晚 10 左右提价的审核,结果10 点多就提示审核通过,当时没看具体时间,就是接盆水泡了个脚的时间审核通过了。所以,我推断小程序审核初次审核会比较严,之后如果改动不大应该直接机审就过了。
总结及对比
这里我们可以对小程序云开发和传统模式做一个对比:
对比条目 | 传统模式 | 云开发 |
---|---|---|
是否需要后端服务 | 需要 (如一个java应用部署在 Tomcat 中) | 不需要 只需要“云函数” |
是否需要域名 | 需要 (还得在微信后台的把域名加入安全域名) | 不需要 |
是否需要购买服务器 | 需要 (你得部署后端 Java 应用,还得安装数据库) | 不需要 开通云开发之后免费套餐够用 不够的话购买套餐按调用量计费 |
是否需要懂运维 | 需要 (你得会折腾服务器,数据库之类的 还得配置好相关的用户,端口,启动服务) | |
图片上传及 CDN | 麻烦 | 简单 |
获取微信 openID | 超级简单,云函数中直接获取 | |
··· |
就对比这么多吧,总之,我非常喜欢小程序云开发,小程序真的可以让你轻松干全栈。或者咱们别动不动就提“全栈”,姑且说,小程序云开发可以让你更简单、更快速、更便宜的实现你的产品落地。我自己开发的云小程序上线之后,使用了一两个月,没出现任何问题。我也不用操心服务器什么的。所以,我已经给身边很多人安利了小程序云开发了。这里我就不贴出我的小程序码了,因为已经正式给我同学的超市使用了,所以不方便让别人去产生测试数据。如果你感兴趣想看的话,可以联系我。邮件[email protected]
Docker & k8s 系列一:快速上手docker
Docker & k8s 系列二:本机k8s环境搭建
Docker & k8s 系列三:在k8s中部署单个服务实例
感谢您的阅读,欢迎您评论交流。PS:博客园已停更,后续请通过邮件或者公众号联系