006.不浅谈,数十条业务线以上的,前端小团队瞎逼基础服务思路
!!!高能预警,长文,我都不知道多少字。
背景
我嘛,虽然不是出身bat,写了三年多业务代码,18年开始带团队至今,从toB的pc、管理台、小程序、微信公众号、app、活动、服务端,都有涉猎。当然公司小,我这种人就是跟着公司一点一点成长起来的,没有前人栽树,只能自己动手,天资不够,只能靠肝。大概在17年底的时候,带我的老大(老大呀,看到文章别diss我)离职了,我就这样被赶鸭子上架(其实我的心态是崩溃的,没玩过呀)做了起了前端负责人,后来经历老员工离职,招聘,新员工入职,公司明确业务,业务量爆发,前端业务线暴涨之后,有幸做一些简单的基础服务,这套东西能让3个前端,应付10条以上业务线,我可以自豪的说1年多以来,单季度,bug数<=1、技术问题延期<=0。经历了百来个活动页,3个移动端,8个管理台,1个pc商城,2个小程序,上千万的pv,各种瞎逼情况慢慢磨练出来的。历时至今,1年半的时间,我算是做出了一些,我想做的事情。
目前全公司涉及前端业务线
mobile 3条
- 商城性质
- 管理性质
- 活动性质
小程序 2条
- 商城性质
- 备用小程序
pc端 9条
- 对外商城性质
- 对外数据管理台
- 内部运营管理台
- 内部自营管理台
- 内部财务管理台
- 半内半外的招商管理台
- 对外第三方商家管理台
- 旧,运营管理台
- 旧,招商管理台
基础服务
技术栈选择
- 移动端
技术栈选择Vue全家桶,从我的视角来说,移动端的交互不会特别复杂,最多sku选择、地址、动画,而且这一块大部分都是纯面向用户的需求,很难做业务收束,而且很难解耦。基于我的思考,我就想到vue了,轻便、简单、插件丰富,vue满足我的所有需求。说简单点,我一个业务new个Vue对象,写一堆配置/方法就搞定了。活动的话,我选择了nuxt,活动这种轻便的东西,我静态化就好了。
- pc端
技术栈选择React全家桶,从我的视角来说,pc端我面向的都是管理台需求居多,涉及的交互可能会相对而言复杂,会有拖拽、富文本、页面编辑、图表等等交互出现,这个时候React这种以Component为基本单位的库对于这类业务来说,就很舒服了,解耦不要太爽。
- 小程序用原生
我这边就只有微信小程序,原生确实够用了,而且原生小程序框架也越来越强大,等需要扩展渠道时,我再选择Taro、mpVue等东西。
- npm
请搭建私有的npm,可以做到公共方法的收集,集中化处理。
- mock平台
搭建0业务入侵的mock平台。
- nginx管理
集中管理前端的nginx。
- git仓库
gitlab天下第一。
- 项目模版
将vue、react根据业务,制作为基础模版,以后展开新业务直接copy即可。
- 持续发布
jekins天下第一
- eslint
服务器初始化
- 脚本
总结:其实最有争议的应该是技术栈的选择了,为啥要既有vue、又有react、还有小程序、nuxt,不好意思,我觉得在不同场景下,使用不同的库是合理的。并且作为一个程序员,你的学习能力跟不上,那你还是自己走吧。我还没上typeScript、Rx.js呢。还有就是招聘问题,不好意思,当面试者问我公司前端技术栈时,大部分都跃跃欲试。成本吧,反正不贵。
具体实现
这里我只对,nginx管理、私有的npm、mock平台、项目模版、服务器初始化,做详细具体解释。其余的提一点,就不做解释了,因为jekins就是配置,这个业务性太强,eslint没啥讲的,git仓库也没啥讲的,小程序原生、pc端、移动端这都是纯业务的东西,也没啥讲的。
nginx管理
新建nginxConfig文件夹,目录结构如下。
nginxConfig
|----- build.sh # 脚本
|----- server.develop.xxxx.com.conf # 对外服务的nginx配置
|----- server.develop.xxxx.com.ssl.conf # 对外服务的nginx,https配置
|----- server.test.xxxx.com.conf # 测试服务器的nginx配置,涵盖所有业务
|----- server.test.xxxx.com.ssl.conf # 测试服务器的nginx,https配置,涵盖所有业务
|----- server.admin.xxxx.com.conf # 管理台的nginx配置
|----- server.admin.xxxx.com.conf.ssl.conf # 管理台的nginx,https配置
复制代码
请善用脚本,其实我只需要将nginx,发布到服务器上面根据不同服务器,cp不同nginx配置,然后relaod即可。nginx重启失败我倒是没有碰过,我用这套已经部署了n台活动服务器、n台管理台服务器。当然,写nginx时请在测试服务器谨慎测试。我一般是凌晨3、4点去折腾的,谁叫我肝好呢。
附上脚本代码
# /bin/bash
echo "请选择你要替换的nginx"
echo "1) 替换xxxx,nginx"
echo "2) 替换xxxx,https的nginx"
echo "3) 替换xxxx,的nginx"
echo "4) 替换xxxx,https的nginx"
echo "5) 替换xxxx,的nginx"
echo "6) 替换xxxx,https的nginx"
read number
case $number in
1)
echo "替换xxxx,http的nginx"
\cp server.admin.xxxx.com.conf /etc/nginx/conf.d/
service nginx -reload
;;
2)
echo "替换xxxx,https的nginx"
\cp server.admin.xxxx.com.ssl.conf /etc/nginx/conf.d/
service nginx -reload
;;
3)
echo "替换xxxx的nginx"
\cp server.test.xxxx.com.conf /etc/nginx/conf.d/
service nginx -reload
;;
4)
echo "替换xxxx,https的nginx"
\cp server.test.xxxx.com.ssl.conf /etc/nginx/conf.d/
service nginx -reload
;;
5)
echo "替换xxxx的nginx"
\cp server.develop.xxxx.com.conf /etc/nginx/conf.d/
service nginx -reload
;;
6)
echo "替换xxxx,https的nginx"
\cp server.develop.xxxx.com.ssl.conf /etc/nginx/conf.d/
service nginx -reload
;;
esac
复制代码
告诉你通过脚本编写好处,别看我现在虽然是手动到服务器上去git pull 然后sh build脚本,我完全可以无缝的切到jekins,因为我是脚本呀,配置执行命令就好了呀。我把输入判断改为常量不就好了么。
nginx配置
我只做了最简单nginx配置,没有优化,我还没空去细致研究,其实这一层还能做很多。但是我简单的需求就是,通过域名的路径去匹配页面,然后proxy。当然我不是单一项目,而是多项目,这里会涉及正则。
附上例子代码
server {
listen 80;
server_name _;
charset utf-8;
access_log /var/www/log/nginx_access.log main;
error_log /var/www/log/nginx_error.log main;
root /var/www/html/xxxx/;
index index.html;
location ^~ /api-xxx {
proxy_pass http://www.xxxxx.com;
}
location ^~ /api-xxx {
proxy_pass http://www.xxxxx.com;
}
location ^~ /aaa {
alias /xxxx;
try_files $uri /xxx/index.html;
index index.html;
}
location ^~ /ccc {
alias /xxxx;
try_files $uri $uri/index.html $uri/ =404;
index index.html;
}
}
复制代码
首先,我这边可能会有www.xxx.com/h5
,www.xxx.com/admin
的情况,而且我会根据/api-xxx
的不同,去请求不同的服务。location ^~ /aaa
是针对spa的配置,location ^~ /ccc
是针对静态化页面的配置。为啥我不用cdn去缓存html页面呢?不好意思业务问题不赘述。上述只是例子代码,你可以看思路,可别直接在线上用,业务不同需求不同。
总结:善用脚本解决问题,减少重复劳动。
mock平台
首先你mock的平台最好做到0业务入侵,只切换变量即可,要配合好注释and文档。我的端口可能面对pc、mobile、小程序等。首先浏览器端,我会针对webpack的开发配置做改动。小程序我会二次封装wx.request
。具体实现例子如下。
所有浏览器端
// 开发环境 webpack dev server配置
const PATH = require('../package.json').conf_liberty['path'];
const URL = require('../package.json').conf_liberty['url'];
"/api":{
"target": URL[PATH],
"pathRewrite": {
"^/api-xxx": "/xxx",
}
}
复制代码
// package.json
"conf_liberty": {
"path": "mock",
"url": {
"mock": "https://xxx.xxx.com/mock/xxx/" ,// mock 数据请求地址
"test": "http://xxx.test.xxx.com", // 测试机的请求地址
"pre": "http://xxx.xxx.com/", // 预发布的请求地址
"online": "http://xxx.xxx.com/", // 正式环境的请求地址
}
}
复制代码
小程序端
// config/url.js
/** * 小程序配置文件、切换环境直接切换变量即可 * @param mock 模拟数据环境 * @param test 测试环境 * @param pre 线上测试环境 * @param online 正式环境 */
const envir = 'online';// 环境阀门
const configMap = {
'mock': {
// mock 数据请求地址
url: 'https://xxx.xxx.com/mock/xxx/',
},
'test': {
// 测试机的请求地址
url: 'http://xxx.test.xxx.com',
},
'pre': {
// 预发布的请求地址
url: 'http://xxx.xxx.com/',
},
'online': {
// 正式环境的请求地址
url: 'http://xxx.xxx.com/',
},
};
const config = configMap[envir];
module.exports = {
baseUrl: config.url,
};
复制代码
// 二次封装的wx.request
// 为什么要封装成class,因为我有业务扩展,看个思路即可。
import {baseUrl} from '../config/url';
class request {
request(params) {
return new Promise((resolve, reject) => {
let params.url = baseUrl + params.url;
wx.request({
...params,
success: (result) => {
//
},
fail: (error) => {
//
},
complete: (response) => {
//
},
});
});
};
}
export default new request;
复制代码
每次开发,当开发人员和后端对好接口文档,到mock服务器写好mock,然后就可以在有数据的情况下愉快的开发了,而且的mock的数据更加全面带有随机性质符合前端开发人员需求,需要debug时甚至可以直接切换线上数据,但是操作线上数据需要时刻注意,这必须要引起开发人员重视。当然带有上传性质的接口,不太好测试。但是这点是可以解决的。需要和后端调试,我切换到test即可,多么的简单。我认为前端的很多的bug问题,都是数据的多样性导致开发人员没有考虑到,所带来的结果。
mock平台的选择
首先,我有两个种做法上的选择,线上服务器mock,本地服务器mock,我选择了线上服务器mock做法,因为我mock的数据会越来越多,提交到git上真难看,而且本地写json的形式,对于文档的整理不太友好,并且业务线确实有点多,需要总线式的管理,所有果断放弃。
接下来,我对比的easy-mock
,yapi
,云效平台
,三种mock服务器平台之后,我选择了yapi
。先来说说我的标准,内网服务、搭建简单、升级容易、依赖少、不花钱,另外2种不是不好,只是我的选择而已。先说说easy-mock
的我的看法,麻烦,依赖了Node
、MongoDB
、Redis
,没有一键安装,一键化升级,甚至我还没找到如何升级,也许我眼拙。云效平台,我就看到了简介,怎么用我都没找到,阿里云的服务嘛,估计还要收费算了。来说说yapi
,首先依赖轻,有Node
、MongoDB
就好了。安装太简单npm install -g yapi-cli
,执行一下yapi server
,配置一下数据库,点一点就ok了。我就花了1个小时左右就搞定了。后续升级yapi update
一下好了。多么的愉快。而且基本满足我的需求,基本的mock、高级的mock、文档导入导出非常完美,甚至能测试线上数据,简单的postman
功能也行,连nginx配置官方都帮我想好了。目前我已经在全部业务线使用,而且推荐给客户端、后端同学使用,只能说好评连连。而且以我粗浅的能力,尚能看得懂yapi
的机制,就算官方不维护了,我也能打打补丁。想知道如何安装的,去yapi官网看就好了。
安装方法
来说说我的安装方法把,首先我会在本地安装npm install -g yapi-cli
,做好基本调试,配置好数据库,我用的是远程数据库。写好config.json
基本配置,然后push到git上。到指定服务器pull即可,安好pm2,启动。后续升级也是这样,先本地升级测试一下,然后到服务器pull重启,当然这是可以结合jekins。
总结:这种工具服务的选择没有啥对错,只要符合当前业务开发,并且可以基本的持续迭代即可,自主研发也好,第三方服务也罢,怎么都行,一切以加速业务开发为导向。
私有的npm
首先业务线有点多,而且基本可以做到一些方法复用例如:客户端版本判断、UA检测、统计服务、JSbridge等等,组件二次封装等。例如:ant design的图片上传,你每次写一堆配置,其实你需要配置的无非是action
,disabled
,onChange
,name
你是不是可以跟后端商量固定action
,给一个当前业务的基础接口做成业务组件。再极端一点,我完全可以做成npm包,让后端同学提供一个完全独立的服务。我发现很多前端,对于UI库是真拿来主义,拿来就用,拜托,你有没有发现,其实你每次用UI库里面的东西,写一坨不累么。人家组件是为了适应90%场景的,而你在实际业务中所用到可能不到10%。请你提高一下自己的效率可好?
例如:
// 经过二次封装的上传组建
let upladFileConf = {
title: '上传',// 按钮内容
disabled: false,// 是否禁用
callBack: (e)=> this.handleUpload(e),// 成功回调
callError: ()=> this.handleError(),// 失败回调
};
<UpladFile { ...upladFileConf}/> 复制代码
// 经过二次封装的弹窗组件
const conf = {
visible: visible,// 是否显示
title: '弹窗标题',// 标题
onCancel: (res)=> this.props.onCancel(res),// 确定按钮or取消按钮,回调
};
return (
<Modal { ...conf}></Modal>
)
复制代码
私有npm服务选择
先说我的需求,简单好用,稳定,方便部署,及时通知,在我对比的cnpm
、sinopia
、verdaccio
、Nexus
之后。我的结论是verdaccio
,cnpm
感觉插件有点少貌似,没有钉钉推送的插件,sinopia
都凉了不考虑,Nexus
吧没必要,我就前端用用而已。verdaccio
目前看到还行,继承了sinopia
,插件满足我的需求,安装简单,上线小半年没啥问题,目前有十几个私有包,连数据库都不用折腾。路径切换选择用nrm
即可。
安装方法
首先我依旧会在本地安装好,npm install -g verdaccio
,配置好config.yaml
,装好钉钉通知,做好目录屏蔽,然后迁移到我的git中,然后书写shell脚本。
# build.sh
# /bin/bash
# 启动私有npm脚本
work_path=$(pwd)
verdaccio --listen 4873 --config ${work_path}"/verdaccio/config.yaml"
复制代码
然后每次我需要调试配置时,我先在本地测试,push一下,到服务器pull一下,执行pm2 start build.sh
或者pm2 restart build
。当然这也是可以加到jekins。
注意
yaml这种配置文件请认真去研究一下怎么写,缩进空格有点不同。storage/.sinopia-db.json
一定要是json格式不能为空,而且内容可以是{"list":[],"secret":""}
总结:其实搭建私有npm不难,难在如何设置私有npm包的发布规则,互相依赖升级等,可以用lerna来做。私有npm规则,以及lerna的使用,等我稍后总结。
项目模版
每次new cli我不反对,但是真的不累么,那么多包要加,有些特有的地方架子还要改。目前我总结出3套,ant-admin-template、nuxt-mobile-template、spa-mobile-template。
实现方法(只以admin例子)
新开目录,然后执行new cli,生成基础项目模版。对基础模版做一些调整,并且安装一些基础包
调整的基础模版
|----- dist/ 正式环境产出
|----- conf/ 配置文件
|----- alias.js 公共路径配置文件
|----- development.js 开发环境配置文件
|----- production.js 正式环境配置文件
|----- oss.js build之后将文件上传到oss
|----- src/ 开发目录
|----- components/ 公共业务组件
|----- pages/ 页面
|----- hoc/ HOC
|----- serverice/ 中间层
|----- utils/ 通用方法
|----- index.css 主css
|----- index.js 主入口文件
|----- router.js 路由装载配置
|----- .editorconfig 统一开发格式配置文件
|----- .eslintrc 开发格式配置文件
|----- .webpackrc.js webpack配置文件
|----- .gitignore git提交屏蔽文件
|----- package.json npm配置文件
|----- index.ejs index.html模版文件
-------------分割线----------------
scr/pages
pages
|----- index.js 出口文件
|----- [name]Page 集成业务代码
|----- index.js 集成页面view,model,router
|----- components 当前业务专属组件
|----- index.js view层
|----- [name] 业务文件夹
|----- model.js model层
|----- [name]Component.js 当前page专属组件
复制代码
可能用到的插件包,可自行删减
{
"axios": "^0.18.0",
"prop-types": "^15.6.1",
"qs": "^6.7.0",
"ali-oss": "^6.0.1",
"underscore": "^1.9.1",
"husky": "1.1.2",
"@xxx/xxx": "^x.x.x", // 私有包
}
复制代码
制作完成,push到git中,如果需要新开管理台,只要pull,npm i
,改改nginx即可。nginx我已经脚本化了,很简单就能部署。
注意
登陆、退出、鉴权,预留空间出来,因为每个项目都会有细微差别,让开发人员自行修改即可。
总结:这种项目模版形式,快速开发新业务线,例如运营管理台、财务管理台、等等内部管理台使用,或者作为spa骨架,小程序骨架,pc骨架,为啥要开这么多管理台?少年,你,财务系统、erp系统、cms系统、售后系统,真的不要切分开来么?有精力做权限切分,搞的一个项目臃肿不堪,不如独立。每个平台有自己的账户登陆权限。简单省事,反正都是一套架子,也不存在什么跨项目。升级的话,基础目录即结构不变,升级npm包、升级私有npm包即可。请记住,看上去合并很容易,但复杂度高。分开会加速开发,同时降低复杂度。
服务器初始化
快速在服务器上安装git、nrm、nvm,当然这个是一次性的,后续我做镜像即可。当然有些特殊情况,我也会用到,例如我要制作新的镜像。直接贴代码把不解释了。
安装git
#!/bin/bash
# 安装最新git
# 需要exit之后再次进入机器,git命令才会生效
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel asciidoc wget
yum install gcc perl-ExtUtils-MakeMaker
yum remove git
cd /usr/local/src/
wget https://www.kernel.org/pub/software/scm/git/git-2.15.1.tar.xz
tar -vxf git-2.15.1.tar.xz
cd git-2.15.1
make prefix=/usr/local/git all
make prefix=/usr/local/git install
echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/profile
source /etc/profile
git --version
复制代码
安装nvm
#!/bin/bash
# 安装nvm作为node版本控制
# 需要exit之后再次进入机器,nvm命令才会生效
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
复制代码
安装nrm
#!/bin/bash
# 安装nrm作为npm线路控制
npm install -g nrm
nrm ls
复制代码
注意:先安装git、nvm,再安装nrm
总结:拒绝重复劳动,我只需要touch git.sh && vim git.sh,拷贝代码,执行即可。当然你可以说制作docker镜像,目前我还没研究透彻。公司专业的运维同学也怪忙的,我只能稍微请教一番,还是我自己先动手把。
非代码层面的测试交付
代码层面,通过mock、eslint、code review、单元测试等手段测试可以良好把控。前端程序员很多问题都是跨端,不同app版本测试所带来的。这里我会要求开发人员空出一天或者半天时间,整理业务点,梳理测试的表格。当然也会有,没有测试到的点,这可以通过补充慢慢完善。这东西一般会在大促使用、或者是重要功能,重要项目使用。梳理完成之后,我都会要求开发人员以邮件形式抄送给我,我会二次检查,在项目上线半天前,我会再次要求开发人员以邮件形式抄送给我查看情况,预留给绩效考核,以及我再次检查确认是否有遗漏。
例如:
移动端
UI兼容测试
iphoneX
- xxx页面
- xxx页面
- xxx页面
iPhone XS
- xxx页面
- xxx页面
- xxx页面
iphone8
- xxx页面
- xxx页面
- xxx页面
小米8
- xxx页面
- xxx页面
- xxx页面
小米7
- xxx页面
- xxx页面
- xxx页面
红米
- xxx页面
- xxx页面
- xxx页面
andorid版本测试
x.x.x
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
x.x.x
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
ios版本测试
x.x.x
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
x.x.x
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
微信端测试
x.x.x
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
pc端
UI兼容测试
xx浏览器 x.x.x版本
- xxx页面
- xxx页面
- xxx页面
xx浏览器 x.x.x版本
- xxx页面
- xxx页面
- xxx页面
xx浏览器 x.x.x版本功能测试
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
xx浏览器 x.x.x版本功能测试
- 页面功能点
- 页面功能点
- 页面功能点
- 页面功能点
总结:不是有专业的测试人员么?不好意思,作为程序员自测都不能通过,还写啥代码,还写啥好代码。bug是跟绩效挂钩的,就问你要钱吗?绩效漂亮了,每个季度发钱,大大的给,不爽么?你出去找工作底气足吗?大声喊出,我有完备的测试流程,我写的代码基本0bug,不骄傲么?
错误监控
抓取页面js异常,上报UA/错误提示信息、分析日志/5xx/4xx、CDN异常监控、设置n min之内5xx,4xx阈值,这些都是基础运维服务的东西不深入。关注小程序的开发 > 错误查询/性能监控/告警设置。这一块我尚未特别深入,其实都是阿里云的服务设置一下,或者每天检查微信公众平台,或者使用第三方监控平台。有机会详谈。
总结:错误监控,大部分都是基于日志系统的,前端唯一特殊的点就是会有js报错的情况,称之为崩溃率。反正基于日志就对了。pv、uv的????喵喵喵
获取最新信息
请用rss订阅的方式,订阅你所使用的开源项目,第一时间获取,version信息、commit信息、fixbug信息,作为leader你要时刻掌握最新咨询,而不是被人告知。
结语
不好意思,洋洋洒洒写了这么多,能看到这里的,也不容易,牛逼了老弟/老哥/老妹/老姐。说老实话,还有很多地方没说,例如:脚本化小程序发布、脚本化发布多个端的小程序、eslint的使用细节、webhook的使用如何禁止merge、githook细节、commit log 规范、打tag包、钉钉的推送、cdn部署、code review的标准、npm包的标准、单元测试的普及、性能监控、api切分、用中间页鉴权、设备指纹、支付安全、将bs构架快读切换cs构架、如何保证多个项目同时在测试环境同时交付测试、灰度发布等等还有很多东西把,这些就等我慢慢体验了,慢慢整理了。
这些东西为就不能称之为架构,只是我个人的一些逗比操作而已,这套东西3~10人小团队,20条业务线,给我的感觉是可以撑住的。前提是在业务量在高速增长的情况下使用。我曾经问过我师傅,为啥,他在的时候不做,明明他都懂。他回答的是:“公司在什么阶段做什么事情,当公司在寻找主营业务,不停试错时,你固化的构架,就不适合这家公司,当公司寻找到这个点之后,你用构架就能快速辅助开发,业务其实没啥写的,就看怎么写的快,跟上市场,让公司能快速响应市场,或者引领市场”。好吧,我服气
还没有评论,来说两句吧...