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/h5www.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-mockyapi云效平台,三种mock服务器平台之后,我选择了yapi。先来说说我的标准,内网服务、搭建简单、升级容易、依赖少、不花钱,另外2种不是不好,只是我的选择而已。先说说easy-mock的我的看法,麻烦,依赖了NodeMongoDBRedis,没有一键安装,一键化升级,甚至我还没找到如何升级,也许我眼拙。云效平台,我就看到了简介,怎么用我都没找到,阿里云的服务嘛,估计还要收费算了。来说说yapi,首先依赖轻,有NodeMongoDB就好了。安装太简单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的图片上传,你每次写一堆配置,其实你需要配置的无非是actiondisabledonChangename你是不是可以跟后端商量固定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服务选择

先说我的需求,简单好用,稳定,方便部署,及时通知,在我对比的cnpmsinopiaverdaccioNexus之后。我的结论是verdacciocnpm感觉插件有点少貌似,没有钉钉推送的插件,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条业务线,给我的感觉是可以撑住的。前提是在业务量在高速增长的情况下使用。我曾经问过我师傅,为啥,他在的时候不做,明明他都懂。他回答的是:“公司在什么阶段做什么事情,当公司在寻找主营业务,不停试错时,你固化的构架,就不适合这家公司,当公司寻找到这个点之后,你用构架就能快速辅助开发,业务其实没啥写的,就看怎么写的快,跟上市场,让公司能快速响应市场,或者引领市场”。好吧,我服气

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值