从0到1,打造小团队前端工程化服务(1/3)

4,263 阅读15分钟

前言

本来想弄在一个文章里面,但是因为这边篇幅限制,又涉及到排版和阅读,不得不放在多篇请谅解,全篇两万多字,八万字符,60多张图,其中部分是多图合并的长图,文章的开头和结尾都有相应的前篇和后篇文章导航

建议先看介绍篇,知道大概的内容和流程

一条龙!CI / CD 打造一个小前端团队工程化服务环境

progress-all-guide

开始

这个如火如荼的大前端时代,vue、react、angular 、flutter、electron、小程序等技术框架百家争鸣,这些都是我们前端拿来干架吃饭的武器,前端工程化体系也逐渐向小公司小团队普及,想或者做为一个小小前端团队的leader,了解如何去搭建一个基础的前端工程化体系服务环境,来帮助小团队的提高开发体验和提升工作效率,还是有必要的。

前端工程化体系工作服务环境主要有:CI / CDnpm私有库api mocker server

来,老板我们先来看一下我们要完成的这一套工程化服务的简介图

简介图

progress-all的副本

东西不多其实就几个

本地开发:编写 eslint 、stylint 和 prettier 规则文件,配合vscode的保存自动格式化,再严格的话加上git hook 来检测(当然如果是项目中途加入规则的话,不建议采用git hook等全代码的格式化功能,团队开发可能会宕机😂)

当我们对特定的分支做 push,或者在仓库执行分支合并更新后,就会触发我们的 CI / CD 服务:去自动构建我们的代码(当然可以加上一些单元测试、代码质量检测等,单页测试教程没有加入哈),构建成功后自动帮我们部署到对应的开发环境、测试环境,预发布环境,部署线上生产环境的话一般是设置手动更新等,当然还需要快速回滚的功能,CI / CD 服务运行的状态最后都要做通知,通过:邮件、钉钉企业微信等,告诉团队或者相关开发人员构建的结果等

知识点大图

FN-basics

CI / CD 流水线

​ CI 代表持续集成(Continuous Integration),CD 代表持续交付(Continuous Delivery)和持续部署(Continuous Deployment)。也可以将它们看作是类似于软件开发生命周期的过程

​ 简单的说,就是在本地更改代码—>git push推送到代码托管—>自动安装依赖,打包测试部署等(开发环境一般自动,生产环境一般是需要手动点击按钮上线)

说多无益看图

vue-ci-desc

CI / CD 流水线工作图

CI-CD pipeline

老实说:test这个阶段暂时是没有做的哈哈哈,不过做小组件库的时候会需要单元测试等,大家知道就好

自动化流程的必要性:避免很多问题,少解决很多冲突,假设你的前端团队有6个人,每个人电脑的系统、node版本,npm版本都有可能不一样,就算是规定统一了,每个人拉取代码源仓库 build 出来的产物也有可能不一样,这样会产生几个问题

  • 耗时:每个人都需要去构建
  • 易冲突:当git做pull ,merge,push等的时候一不小心就会产生各种不必要的冲突要去解决,非常的耗时和不愉悦
  • 缓存失效:构建出来的静态文件的hash不好控制,容易在客户端失去缓存,即使在webpack中设置了contenthash等等优化 例如:一个很大的commit.js,base.js,echat.js vendor.js啊等文件,本来是没有更新的,已经在客户端缓存的了,却在这次更新后hash值莫名奇妙的变化了,再次访问页面后客户端的用户还需要重新去加载它们,浪费资源啊老板

其实这些问题在大公司,人员完善的团队一般不会遇到,因为会有专人负责这方的搭建,但是你知道的嘛,初始的小团队,那种苦只有体验过的才知道 🤣,但是如果你会了,又有点话语权,那这问题就可以迎刃而解了😎

打造自动化构建部署 CI /CD 流水线服务的工具我们这里用的是Jenkins

Jenkins

jenkins

​ ci / cd 现在有不少服务,github的GitHub Actions,gitlab 的Gitlab-CI,gitee的Gitee Go,还有travisNetlify等等,我们用Jenkins,引用官方的话就是:

Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。

为了方便部署和迁移等,我们要在docker上安装Jenkins

Docker

docker

​ Docker 是一个开源,轻量级的应用容器引擎,以前我们想在window折腾linux系统,在上面部署应用来测试什么的,我们通常会安装一个虚拟机,在虚拟机上安装操作系统啊,应用什么的,搞垮了可以重新来什么的,不影响主机的系统,不过虚拟机比较重,启动慢,现在我们用docker,相比于虚拟机装操作系统,Docker是使用容器承载应用程序,轻量,高效,方便快捷的部署

Docker 由镜像(Image)容器(Container)仓库(Repository) 三部分组成。

镜像(Image)

镜像Image就是相当于安装操作的系统盘,U盘等等,里面可以包含node、gitlab等等,当然也可以包含完整的centos系统,甚至是centos + jenkins的或者centos + verdaccio(npm 私有库)

容器(Container)

**容器(Container)**就是实际上跑应用的地方啦,可以理解为一个个互相隔离的小虚拟机,你的镜像就是安装在这里

仓库(Repository)

仓库(Repository) 用于存放镜像,有点类似的git仓库,docker hub是个公共的仓库,不过在我们这边网速慢,一般把源设置为淘宝源等

后面我们会用几个docker容器分别安装jenkinsverdaccioyapi等组成一个单机的小小微服务,现在多多少少知道为什么要用docker了吧

Verdaccio

verdaccio

Verdaccio 是一个 Node.js创建的轻量的私有npm proxy registry ,小团队用这个够

Yapi

yapi

Yapi这是一个api管理平台,前后端分离的时候,api mock显得格外重要,没有api、mock,团队的朋友得在代码中做一堆测试数据,判断条件什么的,后面等接口开发好再删掉测试的数据,在对接接口重新测试,这可一点都不好玩。现在主要的mock系统有rap2eolinkeryapi等等,我们这里用yapi,轻量简单功能好,社区活跃star高,需要mongoDB来存数据

MongoDB

mongo

MongoDB使用C++语言编写的非关系型数据库。特点是高性能、易部署、易使用,存储数据十分方便。这里我们安装是提供给yapi

Git 工作流

简单的先说一下我们小团队这里的 git flow,这样好明白我们接下来的 CI / CD 要为我们做什么

代码运行的环境

一般来说,小公司小团队都会有至少这几个环境:

env

  • 本地开发环境

开发人员自测的,可以是自己本地部署的静态服务器,当然也可类似是运行 npm server类似的环境,本地环境运行的代码可以是任何分支的

  • dev开发环境

这个环境是用开发分支dev产出的代码来部署的,唯一的公用的

  • 测试&预发布环境

这个环境是用开发分支release产出的代码来部署的,唯一的公用的

  • 线上生产环境

这个环境是用开发分支master产出的代码来部署的,唯一的公用的

git 分支模型

先看一下分支的角色功能

git-flow

分支的策略

git-flow-1

dev 是公共的开发分支,不会合并到其他分支去的,7

git-flow-2

所有的分支都是基于master分支检出

  • master :保护分支,对应的就是生产环境的分支
  • release:保护分支,所有开发完成的分支会申请合并到release分支,提供给测试人员测试
  • feature-*:功能分支,具体功能开发
  • dev:开发分支&脏分支,对应的是大家共用的开发环境,上面的代码会部署到一个公共的开发环境,供开发人员做自测,应付一些日常、非日常的调试
  • hotfix-*:bug紧急修复分支,可以直接合并到master,(假如release合并了几个feature分支,正在测试的情况下,发现需要紧急修复的buf,紧急修复测试完毕后,可以直接合并到master,如果合并到release,在由release合并到master,那些正在测试的功能或者还不准备上线的功能就会跟着直接上线了)

工作流程大概是:

git-workflow

  1. 接到需求文档,做评审后分配个每个人或小组的功能开发,相关人员从master 检出功能分支
  2. 开发的时候除了会在本地测试,有需要还会合并到dev分支,在公共的开发环境去自己做测试
  3. 因为在开发功能的期间,可能有hotfix完成合并到master,合并代码的时候习惯merge一下master,防止冲突等
  4. 自测完成之后,申请合并到release,合并成功后部署到测试环境后通知测试人员做测试
  5. 测试通过后,release申请合并到master,准备上线
  6. 如果测试不通过,在功能分支修改后重新merge
  7. 上线成功稳定后删除对应的功能分支,dev 合并最新的master分支

CI / CD 的工作

当我们本地代码分支合并到dev,push推送到远程git仓库的时候,触发任务自动build->build成功后自动部署发布到dev开发环境

当我们在gitee 申请feature分支,合并到release,成功后,触发任务自动build->build成功后自动部署发布到release测试环境

当我们申请release分支或&hotfix分支合并到master,成功后,触发任务自动build->build成功后通过手动部署发布到正式生产环境(生产环境一般是需要多加一步手动发布,点击个按钮发布等操作)

创建仓库

上面的环境清楚了,先按照上面的新建一个仓库吧

你也可以直接拉去我的这里为你准备的初始化仓库 gitee.com/eric-gm/ci-…

安装准备

系统要求

liunx系统,我用的是:centos8, 因为要安装docker,要求内核版本不低于 3.10 这里我是用两台阿里云服务器,一台用来部署jenkins、verdaccio、yapi等做环境部署机,一台做静态资源的服务器装nginx,环境部署机建议2核4G起步,如果有安装Gitlab等,那可得8G起步了老板,能弄个16G当然也是甚好哈哈哈

当然不管的内网服务器还是云服务器,配置SSH连接能很方便的在本地连接到服务器

创建用户

centos系统下创建用户,其他系统的老板遇到问题自行百度吧

  1. 以添加用户名为 longming 的用户为例子,输入命令添加用户、添加用户目录、指定 bash 为 shell
useradd -m -s /bin/bash eric

-m 自动创建用户的家目录,并将/etc/skel中的文件复制到家目录中

-s 指定用户登入后所使用的 shell

  1. 然后对该用户设置密码,输入命令后会提示输入两次密码
passwd eric
  1. 查看当前用户列表
cat /etc/passwd
  1. 为了方便操作,现在我们要给用 eric添加root权限
#开启 sudoers 文件的写的权限,默认为只读
chmod -v u+w /etc/sudoers
#修改 sudoers
vi /etc/sudoers
   -----------------------------------------------
   # Allow root to run any commands anywhere
   root    ALL=(ALL)       ALL
   eric   ALL=(ALL)       ALL (添加这一行)
   -----------------------------------------------
# 记得关闭 sudoers 文件的写的权限,默认为只读
chmod -v u-w /etc/sudoers
  1. 用户切换
# su 用户名,- 作用是改变工作目录 ,- 是 -l的缩写,切换到root用户不需要输入用户名
su - eric
# 接下要为ssh连接做准备了(当然这里你可以用阿里云的控制台配)

  1. sshd_conf 控制远程连接的文件
 vi /etc/ssh/sshd_config
    -----------------------------------------------

   PermitRootLogin no //阻止root用户登陆
   AllowUsers eric  //允许制定用户使用SSH登陆
   //阻止用户密码SSH登陆,如果设置no,证书还没配置对,你就登陆不上了哈哈哈,别慌阿里云的VNC远程连接还能搞回来哈哈
   PasswordAuthentication no
   -----------------------------------------------

SSH配置

1 创建密钥

#window系统
系统盘/Users/$(yourusername)/.ssh
#mac系统
cd /Users/$(yourusername)/.ssh
#执行命令创建密钥对,一路回车不要输入密钥密码(当然要输入密码也随你)
ssh-keygen -t rsa -f $(yoursshname) -C "your_email@example.com"

#如果是复制过来的目录内容啊 .ssh/ ,那么对.ssh 目录执行就行
sudo chown -R username .ssh 

解析:

  • -t :指定密钥类型,默认是 rsa ,可以省略。
  • -C: 设置注释文字,比如邮箱。
  • -f: 指定密钥文件存储文件名,省略的话默认生成 id_rsaid_rsa.pub

-f 指定密钥对的文件名这个比较重要,

因为我们要创建多个密钥对连接对应的主机,这里我创建了几个: gitee-ericaliyun-envaliyun-nginx 代表 连接gitee仓库的、连接阿里云环境机的、连接阿里云静态服务器的

执行完成后.ssh 目录下会出现 gitee-ericgitee-eric.pubaliyun-envaliyun-env.pubaliyun-nginxaliyun-nginx.pub 后缀.pub的,是公钥,要复制到连接的主机去的

例子:看到这个就是创建成功了一个啦,记住是在自己的 ssh目录下运行创建哈 创建的时候一路回车不用输入passphrase,大佬的话随意

➜  .ssh ssh-keygen -t rsa -f aliyun-env -C "451904906@qq.com"
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in aliyun-env.
Your public key has been saved in aliyun-env.pub.
The key fingerprint is:
SHA256:ePnhkUiIHTy8zsdpX1F9MKtC+PJK2F768PjEYuoUFgc 451904906@qq.com
The key's randomart image is:
+---[RSA 2048]----+
|     oE       oo |
|     o++ .    .oo|
|    . +o+ .  .. .|
|      .= = ...   |
|     o+.S.* ..   |
|     .o==* +.    |
|      oo*.B.     |
|     . = X.      |
|     .o =o+      |
+----[SHA256]-----+

2 配置公钥

创建完成后复制创建的公钥aliyun-env.pub

 #cat公钥aliyun-env.pub的内容,复制它
 .ssh cat aliyun-env.pub

现在去登陆到你的环境部署主机,登陆到刚刚创建的用户eric

#查看是否进入用户工作目录
pwd 
/home/eric
#在 /home/eric目录下创建 .ssh目录 设置权限700
mkdir ~/.ssh
chmod 700 ~/.ssh
#创建ssh验证文件、设置权限644
vi ~/.ssh/authorized_keys
chmod 644 ~/.ssh/authorized_keys
-----------------------------------------------
#这里复制你的一开始生产的公钥
ssh-rsa askdlajsdkl是什么的反正就是copy
-----------------------------------------------


现在还要配置一下 ssh登陆的配置文件:/etc/ssh/sshd_config,允许 eric等用户远程登陆

sudo vi /etc/ssh/sshd_config

-----------------------------------------------

PermitRootLogin yes //控制root用户登陆与否
AllowUsers eric  //允许制定用户使用SSH登陆,这里我们把用户eric添加进来
PasswordAuthentication yes //阻止用户密码SSH登陆⚠️⚠️⚠️如果设置no,证书还没配置对好,你就登陆不上了哈哈哈,别慌阿里的VNC远程连接还能搞回来哈哈
RSAAuthentication yes
PubkeyAuthentication yes

-----------------------------------------------
 

保存退出 重启sshd服务

sudo systemctl restart sshd

3 连接远程主机

现在回到本地,配置ssh的配置文件 .ssh/conf(如果没有就创建一个),配置ssh的host

Host env
	HostName 47.115.11.abc
	User eric
	Port 22
	IdentityFile ~/.ssh/aliyun-env

配置好测试连接

ssh env
#第一次连接会提示添加到 known_hosts信任,选择yes

#看到这里就连接成功啦
Last login: Sun Aug  2 03:12:27 2020 from 113.110.38.101

Welcome to Alibaba Cloud Elastic Compute Service !

[eric@jenkins-t ~]$

连接成功后 禁止root登陆和密码登录吧

sudo vi /etc/ssh/sshd_config

-----------------------------------------------

PermitRootLogin no //控制root用户登陆与否
AllowUsers eric  //允许制定用户使用SSH登陆,这里我们把用户eric添加进来
PasswordAuthentication no //阻止用户密码SSH登陆⚠️⚠️⚠️如果设置no,证书还没配置对好,你就登陆不上了哈哈哈,‍别慌阿里的VNC远程连接还能搞回来哈哈
RSAAuthentication yes
PubkeyAuthentication yes
-----------------------------------------------

如果使用mac,可以配合alfred的ssh workflow来开始连接远程主机,配置地址可以参考这文章 alfred集成ssh+iTerm2

一般来说对于预发布和生产环境的机器一般都需要设置堡垒机,登陆之前需要获取口令,验证码什么的,这些也可以配合alfred的,我们这边先简化哈

alfred wkflow ssh

安装使用流程

流程还是有需要先讲一下,让大家明白这大致的路线顺序

  1. docker :安装docker,我们的整套服务将分别承载在各个docker容器里
  2. jenkinsci/blueocean :负责 CI / CD任务:自动打包构建部署等一系列自动化任务 (为了流水线的可视化我们镜像拉取的是这个,其实就是jenkins安装了blueocean的插件)
  3. verdaccio/verdaccio :npm库
  4. mongo: 数据库,这里给yapi用的
  5. yapi:这个镜像得我们来制作
  6. docker-compose:上面需要安装的4个应用容器等,到时候会用docker-compose统一控制:安装删除、启动停止,容器网络连接等

Docker

yum设置

我们用yum来安装docker,先处理好yum

  1. 先备份你的原镜像文件,以免出错后可以恢复
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
  1. 下载wget、创建目录、下载阿里云yum源配置
yum install wget -y
mkdir -p  /etc/yum.repos.d
#注意,这个是要对你的centos版本的,
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo
#Centos-7就对7,
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
  1. 更新yum缓存
#清除原有yum源缓存
yum clean all
#生成阿里云yum源缓存
yum makecache
  1. 升级本地yum包
yum update
  1. 安装 yum-utils,它提供了 yum-config-manager,可用来管理yum源
yum install -y yum-utils device-mapper-persistent-data lvm2
  1. 安装阿里云docker源
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 更新yum索引
yum makecache fast
yum clean all

Docker安装

  1. 安装docker
yum -y install docker-ce
#如果出现问题,运行下来两个命令
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
yum -y install ./containerd.io-1.2.13-3.1.el7.x86_64.rpm

  1. 查看docker版本
docker -v
  1. 将你的用户添加到 docker 的用户组,添加后退出用户重新登陆才能生效,这是避免以后docker操作总是要 sudo
sudo usermod -aG docker $(yourname)
  1. 启动docker服务
sudo service docker start
  1. 开机启动docker服务
systemctl enable docker.service

Docker的基本操作命令

镜像操作

docker search images_name       # 查看仓库的镜像资料
docker pull images_name         # 下载镜像
docker images                   # 显示本地镜像
docker rmi images_name/image_id # 删除本地镜像

容器的命令

docker ps        #查看当前运行的容器
docker ps -a     #查看存在的所有容器
docker stop      #停止容器
docker start     #运行容器
docker restart   #重启容器
docker rm container_id/container_name #删除容器
docker logs [options] container_id/container_name     #查看容器日志,出错或者调试可用
docker exec -it container_id/container_name [/bin/bash 或者 sh]  #进入容器分配一个终端/bin/bash,不存在就用sh
exit #在容器内部 
docker commit container_id/container_name # 将容器

卷的操作

#查看本地volume
docker volume ls
#删除指定volume
docker volume rm volume_id/volume_name
#删除所有的volume
docker volume prune

network(这个我们暂时不用掌握,在[Docker Compose 接管](#Docker Compose 接管)的总结里讲)

#查看docker中存在的网络
docker network ls

#查看网络的详细信息
docker network inspect

#自定义网络(默认是bridge类型)
docker network create front-net

#将容器web1 和 web2 加入网络,这样容器web1 和 web2 用这个来两个名字就能互相ping同,会自动进行DNS解析
docker network connect front-net web1
docker network connect front-net web2

#断开连接
docker network disconnect front-net web1
docker network disconnect front-net web2

下一篇

这个算是准备篇,下一篇我们开始用docker 搭建 jenkins CI / CD服务

点击这里到下一篇

progress-all-guide

获取完整小手册

docker

关注公众号:『前端小手册』,回复:小手册

就能获取PDF版本资源的下载

markdown文档我慢点出来哈,配合typora的night主题来看大概这样↓:

handbook1

handbook2

handbook3

掘金这里我也会尽快上!

感谢你们的关注

最后是非常非常的希望能得到你们的关注啦~~

你们小小关注就是我们大大的动力啊,我们会给你们持续地推送原创和好文

这个是我们公众号的二维码

code1