注册
web

个人创业中的全栈开发经验

前言


个人项目开发创业半年有余,两个项目全部扑街,一无所获。


仔细想来其实也不是什么都没有得到,因为现状就是,我创业开始前能预想到的最坏情况,哪怕一毛钱都挣不到,但是也可以从中积累一些经验,比如微信小程序的开发经验。


我过去7年的工作都是在从事前端开发,从最开始从事IPTV 开发,用原生JS、JQuery 开发运行在机顶盒上JSP 页面;到18年,创建了项目组的第一个Vue 项目,那时候我才算是开始“现代”前端的工作;21年到上海,在新公司开始全面使用React + TS,也就是时至创业开始,我所有的工作技能,都是前端技术,后端相关的只有自己瞎折腾的项目,没有真正应用到实际项目中的,这次也算是逼着自己进步了一把。


技术选型


前端 - 后台管理系统:React + TS,用了Antd 的组件库提供的模板直接创建项目


前端 - 微信小程序:原生微信小程序开发 + Vant Weapp


服务端:微信云开发


为什么要选用以上技术栈,只有有一个原因,就是成本极低!非常低!并且很稳定,前后端全部用JS 搞定;后台管理系统部署在腾讯云的Web 应用托管上,直接免去运维工作。说个题外话,前几年自己搞个人网站的时候,服务器是薅的阿里云的羊毛,结果就是啥活都得自己干,用Express 框架开发的后端服务,用Nginx 做代理,结果并发超过100个 服务器直接挂掉。。


现在这一套技术栈,几乎没有学习成本,腾讯云的Web 应用托管集成了CI 工具,提交代码到线上分之后,自动部署,用了半年多,网站、小程序都没有挂掉过。(我真不是腾讯的托。。)


后台管理系统


React、TS、Antd 业务开发技术不多赘述,讲讲怎么在Web 端请求微信云开发的接口吧。


微信云开发提供了可访问云服务的Web Sdk,引入sdk 后,只需要进行简单的初始化,即可访问接口。


云开发登录授权配置,打开匿名登录


image.png


示例代码

处理请求


import cloudbase from "@cloudbase/js-sdk";
...
const env = ""; // 环境id
const clientId = ""; 终端id

// 创建实例
const app: any = cloudbase.init({
env,
clientId,
});

const auth = app.auth({
persistence: "local",
});

...
// 请求方法
export const cloudFn = async (
type: string,
params?: any
): Promise<any> => {
// 判断登录态
if (!auth?.hasLoginState()) {
localStorage.clear();
await auth.signInAnonymously();
}

const res = await app.callFunction({
name: "xxxx", // 云函数名称
data: { type, data: options?. }, // 传参
parse: isDev, // 环境
});

// 根据自己的业务方式处理返回数据
...


处理接口


import { cloudFn } from "@/utils";

export const xxx = (params: API.xxx) => {
return cloudFn("name", params);
};

Web Sdk 官方文档:docs.cloudbase.net/api-referen…


部署

提交代码到部署分之后,会自动部署,访问web 应用托管,会提供一个默认访问的域名,可以直接访问,但是不推荐生产使用,只需要再配置一个域名就好了。


微信小程序


如果没有开发过微信小程序,去看一下官方文档,前端基本可以无成本上手,参照官方文档开发就好;为什么组件库选择Vant Weapp,基本补全了官方没有提供的组件,使用方式也很简单,实际使用后体验不错,值得推荐。


微信云开发


我用Java、python、node 都写过后端接口,对于一个前端来说,单论简单、好上手而言,微信云开发,我愿称之为YYDS!就两个字,简单!


官方提供了请求的方法,我对其简单的封装了一下,如果觉得不错,尽管拿去用,如果有不完善的,还请指正


示例代码

云函数入口 index.js

const user = require('./user);

exports.main = async (event, context) => {
switch (event.type) {
case "userGet":
case "userUpdate":
return await user.main(event, context);


default:
return {
code: -1,
msg: '
接口不存在'
}
}
};

user 入口

const get = require("./get");
const update = require("./update");

exports.main = async (event) => {
const apiType = event.type
const data = event.data || {};

if (apiType === 'userGet') {
return await get.main(data);
};

if (apiType === 'userUpdate') {
return await update.main(data);
};
};

user/get.js

const {
dbGet, // 通用get 方法 (见后问)
filterParams, // 清除异常参数,比如空字符串,null 等
} = require("../../utils");
const check = require('./check');

exports.main = async (data) => {
// 校验参数
if (check(data)) return {
code: -1,
msg: check(data),
}

const params = {
offset: data.offset,
limit: data.limit,
name: data.name,
};


// 模糊搜索
if (params.name) {
params.name = {
$regex: ".*" + params.name,
$options: "i",
};
}

return await dbGet("user", filterParams(params));
};

user/update.js

const {
dbUpdate
} = require("../../utils");
const check = require('./check');

exports.main = async (data) => {
if (check(data)) return {
code: -1,
msg: check(data),
}


const params = {
_id: data._id,
name: data.name
};

return await dbUpdate("user", params);
};

utils.js

const cloud = require("wx-server-sdk");

// 初始化云环境
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
});

const db = cloud.database();

async function dbGet(
databaseTable, // 表名
params, // 参数
orderByKey = "", // 排序参数
order = "desc" // 排序方式
) {
const pageInfo = {
offset: params.offset || 1,
limit: params.limit || 10,
};
delete params.offset;
delete params.limit;

try {
// 获取总数
const resCount = await db
.collection(databaseTable)
.where(params)
.count();

const resCountData = formatRes(resCount)
if(resCount?.code !== 0) {
return resCountData
}

// 总数是0,直接返回数据
if(resCount?.data === 0) {
return {
code: 0,
data: { data: [] },
total: 0,
}
}

// 获取数据
const res = await db
.collection(databaseTable)
.where(params)
.skip((pageInfo.offset - 1) * pageInfo.limit) // 分页
.limit(pageInfo.limit) // 最多几条
.orderBy(orderByKey, order) // 排序
.get();

// 处理返回数据
const resData = formatRes(res);
if(resData?.code === 0) {
return {
code: 0,
data: {
data: resData?.data || [],
total: resCountData?.data || 0
},
}
} else {
return resData
}
} catch (error) {
return {
code: -2,
data: null,
msg: "请求失败",
};
}
}

async function dbUpdate(databaseTable, updateData) {
let res;
let isSuccess = false;
try {
const params = updateData;

if (updateData._id) {
// 编辑
delete params._id;
res = await db.collection(databaseTable).doc(updateData._id).update({
data: params,
});

if (res.errMsg === "document.update:ok") {
isSuccess = true;
}
} else {
// 新增
res = await db.collection(databaseTable).add({
data: params,
});

if (res.errMsg === "collection.add:ok") {
isSuccess = true;
}
}
if (isSuccess) {
return {
code: 0,
_id: res._id,
msg: `${updateData._id ? "更新" : "新增"}数据成功`,
};
} else {
return {
code: -1,
data: null,
msg: `${updateData._id ? "更新" : "新增"}数据失败`,
};
}
} catch (error) {
return {
code: -1,
data: null,
msg: `请求服务器失败,${updateData._id ? "新增" : "更新"}数据失败`,
};
}
}

function formatRes(res) {
const cloudFnMsgList = ["document.get:ok", "collection.get:ok", "collection.count:ok"];

if (cloudFnMsgList.includes(res?.errMsg)) {
return {
code: 0,
data: res.data || res.total,
};
} else {
return {
code: -1,
data: null,
msg: "请求服务器失败",
};
}
}

module.exports = {
dbGet,
dbUpdate,
formatRes,
};

差不多到此就结束了,Web 端的后台管理系统,微信小程序的后端接口实现了,并且可以互通,这种方式是我实践过,在保证业务、性能、稳定的前提下,最低成本的全栈开发方案,如果有其他更好的方案,欢迎讨论。


作者:鹿林秋月
来源:juejin.cn/post/7294056563631079424

0 个评论

要回复文章请先登录注册