现在前端把戏越来越多了,今天我要谈的并不是什么别致的东西了,主动化构建布置嘛,假如你是一个 Javaer 或许 运维同学,关于 Jenkins 之类的主动化布置必定不陌生。不过也说到过了,作为一个前端,特别是业务驱动的开发来说,平时必定是很少接触这些东西的。笔者也是最近才打算前端主动化布置上容器,然后学习看了看,接下来就把学习进程和小总结给咱们共享共享,a f / D l ~ r很浅显,大牛直接右上角(左上角)封闭就能够了。
我写文章的主旨便是,把自己走过的弯路总结给咱们,f G ! 0 h防止你们踩坑I d y x 1 {,不 u f h图你们点赞,少喷就好。由于确实经历过很屡次“文章千百万,实践就完蛋”的场景太多了,咱们也不对读者负责,所以我的文章一般都会有代码和 Demo 示例,做不^ 5 c ~ 5 c y到最好可是至少假如你遇到过相同的问题t G ; a,必K ` M 7定能解决~
前置
- Gitlab
- Gitlab Runner
- Docker
上面归于前置内容,Gitlab 就不用说了吧,一般公司内部运用的都是 Gitlab 库房;Gitlab Runner,一般需求额定装置,预先编写的主动化构建布置的脚本(后面会介绍到)便是由它来运转的: m k T K % _ d;最后,项目要打包成镜像布置到容器上,所以也需求 Docker。r = M g v e 3 f C
由于是公司内部流程不是自己单独玩耍,所以让运维c C _ [ c V ;大大替你搞定就能够了,现在这个时代在公司运用应该都是默认会有的了。个人= 1 / x / [项P & c + z n .目或许大概率应该是放在 Github 上的,小伙伴们能够挑选 Github Actions,网上有许多教程。
新建一个项目
以 crea3 4 5 hte-react-app
为比方简略介绍一下,主动化构建布置然后生成 Gitlab Pages。首要,咱们新建一个项目推送到长途库房:
.gitlab-ci.yml — 初始化
在运用 Gitlab CI 进行主动化构建布置的时分,需求新建一个 .gitlab-ci.yml
装备文件,里边是咱们主动化构建的详A : 8 o _ 8细步骤的脚本,这儿先简略的进行初始化一下,下面会详细; X X a f介绍:
# 界说阶段 stages
stages:
- build
- deploy
# 界说 job - build 项目
job1 - build 阶段! 9 M ( = 3:
# 开端之前需求装置依靠
stage: build
script:
- echo "finisu 6 Gh build stage"
# 界说 job
job2 - 发布到线上环境:
stage: deploy
script:
- echo "finish deploy stage"
上U i K a 1面装备文件大体意思便是,此项目的主动构建大致分为两个阶段,分别是 build 和 deploy 阶段,而且每个阶段都会履行一些相应的使命,这儿由于是初始化演示,仅仅简略的进行了两行文本输出,而且字段意义咱们也不需求知道,下面会详细介绍。
将文件推送上去,检查作用:
从图中能( 0 2 `够看出,成功推送到长途,接下来点击: CI/CD
-> pipelines
从上图能够看到,项目的主动化构建就完成了,你或许会问了,这么简略?其实便是这么简略,尽管我9 @ ) C r ^ L将构建内容简化成了两行输出,可是整体流程其实是不变的,无非便是构建进程复杂化,增加脚本内容罢了。接下来,就用此比方,一步一步加深了解 Gitlab CI。
Gitlab 中 YAML 相关概念解析
前面说到了,一切的构建布置内容g d z 8 K a都是写在 .gitlab-ci.yml
脚本@ F n ` X B N ,里履行k I n s $ i的,因此,此文件的内容写法以及各个关键字对应的意义,6 w X & x w是首要要了解的。
官方文档在此,我仅仅官方文档的筛选搬运工,咱们也能够自己去《有道词典》翻译。
关键字 | Reqired | 描绘 |
---|---|---|
image | 否 | 运用 Docker 镜像 |
service | 否 | 运用 Docker 服务 |
stages | 否 | 界说构建阶段 |
t2 f ) 1 x 5 N X 2ypes | 否 | stages 别名(建议+ + 8 x E 4 .只运用st| 2 +ages,现已被废弃) |
before_script | 否 | 每个脚本使命履行之前履行的脚本 |
after_scriptw R i | 否 | 每个脚本使命履行之; q y e o ? k后履行的脚本 |
variables | 否 | 界说变量,能够在0 9 0 v a B +构建阶段运用 |
cache | 否 | 界说缓存文件[ I 5 ) q l c r #,能够在后面阶段运用到 |
job
job
是 .gitlax } Q g D : Cb-ci.yml
里的尖端元素了,任何主动# ! W L 7 $ D 6化布置都必须有的,个人认为能够将它分红使命,每个使命里至少包括一条脚本表J w v `明在此使命里要做的事情。能够界说多个 job
而且每一个 jJ + dob
之间都是相互独立的,job
会被 Gitlab Runner
在自己的环境下履行。
# 界说 job1
job1:
script:
- echo "i'm job1"
# 界说 job2
job2:
script:
- echo "p # E J c u 6 _ wi'mT e x 8 # 7 [ job2"
上面是最简略的示例,界说了两个 job
,每个里边有一个脚本执输出一段字符M 2 6 b串。
【留意】: 前面说到过r e I q,
job
是尖端元素,i 4 : r m l = ^它的命名也很宽泛,${string}:
字符串 + 分号(不限中英文3 R B)即可,可是上面表格说到的各个关键字是不能被界说成job名
的。
image && services
由于 Gitlab Runner 也是运用 Docker 进行构建的,因此能够在# h D y x _构建咱们代码的时分也运用相应的镜像进行根底构建。对应字段便是 image
和 services
,先来看看官方给的简略示例:
# 根底镜像
image: ruby:2.1
# 运用镜像 service - postgres
services:
- postgres
接下来咱们看看咱们自己的项目,咱们是一个基于 create-react-ap) h P G } y vp
构建的项目,所以依靠的必定是 node
镜像,服务不需求能够不写,由于是可选项。
# 依靠镜像 node
image: nod! O G 3e:10.16.0
# 界说阶段 stM 1 ~ages
stages:
- build
- depl8 v u U yoy
# 界说 job - build 项目
job1 - build 阶段:
# 开端之前需求装置依靠T G I
stage: build
script:
- echo "finish build stage"
# 界说 job
job2 - 发布到线上环境:
stage: deploy
script:
- echo "finish deploy st} s K h ,agL u (e"
上面,咱们增加了镜像依靠,而且拟定版本号是v10.16.0
。
stages
这个字段也挺重要的,我觉得O ? & 4 2 3能够翻译为为构建阶段,比方咱们的项目分为两阶段,第一个阶| z A R W d u段是 build
— 编译打包,第二个阶段是 deploy
— 发布上线。其实也便是对应两个p x e b job,然后鄙2 O L j人面对每一个阶段更详细化的描绘。
s| P ~ / T x Gtages
字段界说O N 7 j B B O ) A的几个阶段在 pipelines 构O R O O D C 9建进程中顺序是一致的,而且有如下规律:
- 前一阶段完成,后一阶段履行
也便是说,build 成功了,deploy 才会履行。
- 一切阶段悉数成功,整个 pipelines 进程悉数标记为 pQ } ) v 9 Y ~ H ^ass,整个构建才是成功
- 其中一个6 n * a阶段失利,pipelines 后续流程不会被履行,整个构建标记为失利。
详细履行进程咱们能够在 pipelines
里检查到,如下图所示
sB ) 7 1 ~cript
这个也算是最重要的一1 N M k c个字段了,它表明由 Gitlab Runner 履行的一段 shn O n yell 脚本,在构建项目进程中必定是要履行许多指令的,比方装置依靠、打包、布置等指令。仍是以咱们的项目为例,7 8 o新增了 node 镜像,这就意味着能N m H &够履行 npm install
和 npm run build
等指令了。
# 依靠镜像
image: node:10.16.0
# 界说阶段 stages
sta. Z V jgesM H T _ e:
- build
- deploy
# 界说 job - build 项目
job1 - build 阶段:
# 开端之前需求- : * G # Z g ; J装置依靠
stage: build
script:
- yarn install
- yarn build
- echo "finish build stage"
# 界说 job
job2 - 发布到线上环境:
stage: deploy
script:
- echo "finish deploy stage"
在上面,咱们在 job1 里新增了两个指令 yarn install
和 yarn build
两条指令,熟悉前端开发的应该都知! U * 4 o q E ) N道,项目生产之前要装置依靠和打包编译。接下来推送到长途库房来看看作用:
- 构建成功
- 第一步的构建内容x P e 6 W 3
从上方截图能够看的出来,推送上去的代码再次触发主动构建,构建成功而且第一步 build 阶段里边顺次履行了咱们编写的三个脚本内容,十分完l _ V ^ J美~
before_script 和 after_script
这两个字段意义就跟字面意义一致,before_script
— 脚本履行之前履行的脚本,after_script
— 脚本履行; j c | J之后履行的脚本。
这儿或许有人会说B x a了,那么把 yarn install
安依靠的脚本指令放到 before_script
里岂不是愈加适宜,这样 build 阶段只做 build 指令,愈加恰当。答案是不可的,由于这两个指令是在外层,意思是每一个阶段之前都履行一次,也便是说,每j U 0 I x q I m $一个 job 里都会先履行 b[ Y t n wefore_script
然后再履行自己界说的 script 脚本,而事实上咱2 2 K c b们 yarn install
只需求履行一次。
我思来想去想} d – g l w找一个D o C } ,最佳场景去演示,可是感觉用到的场景确实很少而且也都不是很恰当,当然q M * – $ d,假如仅 h n j仅为了了解功用,那么输出一个字符串就行了,这儿我觉得国内能够在 before_script
前W l = N ) : w –设置下淘宝镜像。
# 依靠镜像
image: node:10.16.0
be4 i 2fore_scripU / V { = %t:
- echo "======== before script ========"
- npm config set regM b g p Q 0istry https://regq b u ?iste q 1 i W $ qry.npm.taobao.org
after_script:
- echo "=======v $ p 7 o= after scrip% | y t Dt ========"
# 界说阶段 stages
stages:
- build
- deploy
# 界说 job - build 项目
job1z M X 1 V w - build 阶段:j F 6 * m E . z
# 开端之前需求装置依靠
stage: build
script:
- yarn install
- yarn build
- echo "finish build stage"
# 界说 job
job2 - 发布到线上环境:
stage: deploy
script:
- echo "finish deploy stage"
来看看作用:
- bd _ 2 N E E 8 $ Nuild 阶段
- Deploy 阶段
能够看到确实如描绘所A Z V C | J D言,这两个脚本每个构建阶段 — stage 都会履行。
only && except
接下来这两个关键字也很重要了,咱们先来看一下比方:
- 第一步,新建/ e , ^ l H , G %一个分支:
branch-a
- 第二步,修正内容推送到长途
先别管是否构建成功了,现在就出问题了。为啥?咱们研讨的是主+ % q [ + o动化构建布置上线,那么必定是应该有上线标准的,你不能每个分支每次 push 到长; u ` B V :途都触发构建吧,必定不可啊。这时分,only 和k P 5 3 s ] k / f except 就派上用场了。
- only:只允许契合条件的触发构建
- except:除了某些内容,都会触发构建r P p
这儿为了演示,我约定的是,只要e d y b e J masterC F 9 的 push 会触发,只要 master 分支代码变化了,才会触发构建。
# 依靠镜像
image: node:10.16.0
before_script:
- echo "======== bew * Ufore script ========"
- npm coZ / # s b o y 3 %nfig set rel d / X U f / {gistry https://registry.npm.taobao.org
after_script8 , * n U ` P P:
- echo "=====H ] K=== after script ========"
# 界说# m D ( { D p x l阶段 stages
stages:
- build
- deployz D J
# 界说 job - build 项目
job1 - build 阶段:
# 开端之前需求装置依靠
stage: build
script:
- ya* ; 8rn install
- yarn build
- echo "finish build stage"
only:
- master
# 界说 joq R 7 O j B 1 * )b
jh f v p Bob2 - 发布到线上环境:
stage: deploy
script:
- echo "finish deploys $ ] stage"
only:
- master
【留意】:only 字段是需求每个 job 阶段都要单独界说的,由于不能保证你每个阶段对应的要求是什么。
将代V O k ] k 7 c _码推送上去,现已不会触发主动构建了,咱们再来验证一下,在 branch-a
分支提一个 MR 然后合并到 master,看看作用。
- Merge Request
- Merge && CI
能够看到,分支提交并不会触发 CI,而 Merge 到 master 之后会触发,达到预期。
关于 only 和 except 相关内容其实还有许多,比方特定分支,特定 tag 等等。这儿就不做过多赘述,总归便是能够满意你任何复杂场景和操作,你自己去组合就好了。
variables
望文生义,便是变量,咱们能够预先界说+ ; $ a b ?好一些常用的变量,然后在 job 的脚本里运用它们,一个简略的比方:
variables:
DOCKW Y ! . $ , y :ER_HUB_URL: "https://custom.dockerhub.com/ { i & * Y"
# 界说 job - build 项目
job1-build:
# 开端之前需求装置依靠
stage: build
script:
- yarn install
- yarn build
- ec( f + F [ b m t /ho $DOCKER_HUB_URL
- echo "B ^ b f Vfinish build stage"
除了自界说的变量之外,系统还内置了许多常量:详细检查这儿
artifacts
这个参数也是十分重要的一环,它的作用是能够在当时 job 构建成功之后,将构建列表里的文件或许文件夹传递给其他的 job(不一定便是下R 9 A 5 i一个 job),也便是说在两个 job 之间进行传递文件内容。
为什么说它重要呢,咱们先来看看比方,咱们在 job2 中新添加一个指令,检查当时构建目录:
# 界说 job7 } B C k
job2 -6 N r b E v J 发布到线上环境:
stagej 6 r M k: deX a 3 . d * C r =ploy
script:
- ls
- echo "finish deploy stage"
only:
- mas, ` z N - V %ter
输出成果如下:
咱们会发现一个问题,在| P } job2 里获取v U V ^ B 4 V的仍是库房 master 里的内容,这意味着什么,假如你了解 React 应该知道,create-react-app
打包之后会生成一个 /build
文件夹,此文件夹里边的内容$ q W k 9 R一般来说便是最终的上线| T e * t K ` s内容。可是咱们分明在 job1 里边 build 了,而且 job1 build 成功了,也便是说需求把 job1 build 成功过后的文件夹 /build
传递给 job2,所以此刻也就用上了 artifacts
。
# 依靠g J i x s A { p镜像
image: node:10.16.0
before_script:
- echo "======== before script =======3 o 2 i="
-? T 4 E [ H ! s npm config set registry https://registry.npm.taobao.org
after_script:
- echo "======== after script ========"
# 界说阶段 stages
stages:
- build
- deploy
# 界说 job - build 项目
job1-build:
# 开端之前需求装置依靠
stage: build
script:
- yarn install
- yarn build
- echo "finis| F & I f sh build stage"
only:
- master
artifacts:
paths:
-B L 9 K # build/
# 界说 job
job2-deploy:
stage: deploy
scripV 4 ` v vt:
- ls
- echo "finish d] E 5 V {eploy stage"
only:
- master
dependencies:
- job1-build
- job1-4 0 4build
Job1 新增的 artifactK ! d g 5 =s
里边设置 paths: build/
文件夹。
- job2-deploy
Job2 新增 dependenc* O A P z G u 9 Uies: job1-build
,表明此 job 依靠 job1-build
传递过来的 artifacts
内容。
推送到长途检查作用:
从上图能够看出,job2 现已能够获取到 job1 构建成功之后生成的 /build
文件夹了。
.gitlab-ci.yml
最后的装备文件如下所示:
# 依靠镜O A o像
image: node:10.16.0
before_script:
- echo "======== before script% ^ q E M q | M d ========"
- npm config set registry https://registry.npm.tao# y L 6 T z ebao.org
after_script:
- echo "======== after script ========"
# 界说阶段 stages
stages:
- build
- deploy
# 界说 jm Q _ bob - build 项目
job1-build:
# 开端之G N - V前需求装置依靠
stage: build
script:
- yarn install
- yarn! C P * G { O u 0 build
- echo "finish bZ f q #uild stage"
only:
- master
artifacts:
paths:
- build/
# 界说 joby * Z 3 0 5
job2-deploy:
stage: deploy
script:
- ls
#######
# 这儿能够对项目. f i n S 2 7 s ,进行真实的发布
#######
- echo "finish deploy stage"
only:% ! h 9 ` ` .
- master
dependencies:
- job1-build
其实真实的主动化构建布置上线也@ J 0 = p Z便是在
job2-deploy
里边再新增更复杂的脚本罢了,比方笔者做的便是打包 docker 镜像推送到 docker hub 然后经过 k8s 布置项目。J f C ) Q z O O当然,也能够增 D f z 5 G ! –加 stage 和 job,详细细节每个人每个公司都不一样,咱们能够自行修正。
项目构建流程系统准则
前面介绍完基本上前端使用 Gitlab UI 就能够进行简略的主动化布置上线了,只不过在公司多人开发的时分要标准一些,下面是我个人(个人看法,不喜勿喷)觉得比较标准化的合理流9 k ) t Y z ] 程。
- 并行开发项目,每次上线 master 分支
- 基于 master 分支新开分支开发(单人 && 多人)
- 分支开发结束预备上线前提 Merge Request,code-review 没问题后由 Masters 进行 Mef ? + + L u ; * Vrge 到 master
- master 分支改变触发 Gitly C ; 5 { n hab CI 主动构建布置上线(E } 9 ;上线失利回滚也是主动触发)
因此,Gitlab 项目装备应该是如下:
- master 分支在新增完l f –
.gitlab-ci.yml
之 @ h t 5 / !后设置不允许 push - master 分支只能够由管理: 9 C x j员经过 Merge Request 进行代码的合? q u & g D h 8 [并
总结
很浅显的一篇文章,仅仅为了让咱们能简略了解前端主动化构建,以及个人的一些小小总结。更深层次的比方Gitlab Runner
和实际项目的Docker
布置由于因人而异,也并不是一切人都用 Docker 布置前端,所以没过多介绍,我觉得作为入门了解 Gitlab CI 还 OK~