前端高階進階:CICD 下前端的多特性分支環境部署

shanyue發表於2020-03-11
  1. 前端高階進階:javascript 程式碼是如何被壓縮
  2. 前端高階進階:如何更好地優化打包資源
  3. 前端高階進階:網站的快取控制策略最佳實踐及注意事項
  4. 前端高階進階:在生產環境中使你的 npm i 速度提升 50%
  5. 前端高階進階:使用 docker 高效部署你的前端應用
  6. 前端高階進階:CICD 下的前端多特性分支環境的部署
  7. 前端高階進階:前端部署的發展歷程

更多文章: 前端工程化系列


我在 github 上新建了一個倉庫 每日一題,每天一道面試題,歡迎交流。


無論大中小企業,多特性分支的前端環境基本上已成為了標配,即每一個功能分支都配有相應的測試環境。今天山月就循序漸進來講解下多分支環境的實現方式,經濟基礎決定上層建築,企業的基礎服務建設決定實現方式,這裡是基於 Docker 與 CICD 的實現。

至於伺服器端的多分支環境部署,由於都是基於容器的思想,思路與前端一致,如果直接想看結論,請翻到最後看小結。

從前後端的開發到上線,不同的企業對不同的環境有不同的命名,甚至有更精細的劃分。但是一般可以可以劃分為三個環境,我把這三個環境命名如下,並會在下述

  1. local:本地環境,把專案 git clone 到自己的工作筆記本或者開發機中,在 localhost:8080 類似的地址進行除錯與開發。此時環境的物件導向主要是開發者。
  2. dev:測試環境,本地業務迭代開發結束並交付給測試進行功能測試的環境,在 dev.shanyue.tech 類似的二級域名進行測試。此時環境的物件導向主要是測試人員。
  3. prod:生產環境,線上供使用者使用的環境,在 shanyue.tech 類似的地址。此時環境的物件導向主要是使用者。

那什麼是多分支環境部署呢?這要從 Git 的工作流說起

本篇文章要求你有一定的 Docker,DevOps 以及前端工程化的知識儲備。如果沒有的話,本系列文章以及 個人伺服器運維指南 中的 Docker 部分會對你有所幫助。

Git 工作流

隨著不同的環境的區分,基於版本管理工具演化出了各種各樣的工作流,比如 Git FlowGithub FlowGitlab Flow。這裡簡單介紹一種最常見的 Git Flow

git flow

git flow 流程如圖上所示,關於細節這裡不作過多的討論。一般來說

  1. feature 分支對應本地環境
  2. develop 分支對應測試環境
  3. master 分支對應生產環境

由於每次 feature 開發結束後都要合併到 develop 分支進行測試。此時會有幾個問題

  1. develop 分支測試出現 bug 後,每次修復後都需要合併到 develop 分支。
  2. 當多功能同時開發時會造成 develop 分支的擁擠導致,各個功能最後只能統一上線,因為它無法時刻保持一個乾淨的 develop 分支,這與我們現在所提倡的敏捷開發,小步迭代格格不入。

此時,基於 feature 分支急需一套可單獨測試的環境

多分支環境部署

CI,Continous Integration 持續整合使專案變得更加自動化,充分減少程式設計師的手動操作,並且在產品快速迭代的同時提高程式碼質量。基於 CICD 的工作流也大大改善了 Git 的工作流。其中就增加了一個基於分支的前端環境:

  1. 特性環境 (也不知道叫啥名字,就這麼起吧),對應於 feature 分支。每個 feature 分支都會有一個環境,可以視為本地環境與測試環境的結合體。如對功能 feature-A 的開發在 feature-A.dev.shanyue.tech 類似的三級域名進行測試。

此時對於開發,測試,產品交付來講,整個流程的體驗就順滑了很多。於是終於到了今天的正題:

如何實現多分支環境部署?

基於 docker 進行部署

由於 docker 的輕便易用,隔離性好並且可移植性高的特點,這裡選擇基於 docker 的部署,映象配置檔案如下所示。

FROM node:10-alpine as builder

ENV PROJECT_ENV development
ENV NODE_ENV production

# http-server 不變動也可以利用快取
WORKDIR /code

ADD package.json package-lock.json /code
RUN npm install --production

ADD . /code
RUN npm run build

# 選擇更小體積的基礎映象
FROM nginx:10-alpine
COPY --from=builder /code/public /usr/share/nginx/html
複製程式碼

另外由於此時不在生產環境,完全沒有必要把所有靜態資源扔到 CDN 去處理,甚至為了方便除錯,在打包時也可以避免做過多的混淆及壓縮。如果你對 docker 不熟悉,可以檢視本系列暨前端工程暨高階前端進階的系列文章第 N 篇:使用 Docker 部署前端專案

基於容器的前端部署與反向代理

現在流行的 kubernetesdocker-compose 應用編排都是基於容器的,所以我們只需要著力於容器,思考如何利用它做多分支部署。

首先解決的問題是多分支部署環境的多域名問題,因此首先要了解如何利用容器來對映域名,以下是兩種常見的方案,但是利用容器的 label 的方式還是多一些

  1. 基於 container label,如 traefik 以及 kubernetes ingress
  2. 基於 environment,如 docker-nginx

但是無論基於那種方式的部署,我們總是可以在給它封裝一層來簡化操作,一來方便運維管理,一來方便開發者直接接入。如把部署抽象為一個命令,我們這裡暫時把這個命令命名為 deploydeploy 這個命令可能基於 kubectl 也有可能基於 docker-conpose

該命令最核心 API 如下:

$ deploy service-name --host :host
複製程式碼

假設要部署一個應用 shanyue-feature-A,設定它的域名為 feature-A.dev.shanyue.tech,則這個部署前端的命令為:

$ deploy shanyue-feature-A --host feature-A.dev.shanyue.tech
複製程式碼

現在只剩下了一個問題:找到當前分支。

基於 CICD 的多分支部署

在 CICD 中很容易獲取當前分支的資訊,在 CI 環境中可以通過環境變數獲取到。

如在 gitlab CI 中可以通過環境變數 CI_COMMIT_REF_SLUG 獲取,該環境變數還會做相應的分支名替換,如 feature/Afeature-a 的轉化。

  • CI_COMMIT_REF_SLUG: $CI_COMMIT_REF_NAME lowercased, shortened to 63 bytes, and with everything except 0-9 and a-z replaced with -. No leading / trailing -. Use in URLs, host names and domain names.

以下是一個基於 gitlab CI 的一個多分支部署的簡單示例

deploy-for-feature:
  stage: deploy
  only:
    refs:
      - /^feature\/.*$/
  script:
    - deploy shanyue-$CI_COMMIT_REF_SLUG --host https://$CI_COMMIT_REF_SLUG.sp.dev.smartstudy.com 
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_SLUG.dev.shanyue.tech
複製程式碼

小結

隨著 CICD 的發展,對快速迭代以及程式碼質量提出了更高的要求,而基於分支的多測試環境則成為了剛需。對於該環境的搭建,思路也很清晰

  1. 借用現有的 CICD 服務,如 jenkinsgitlab CI 或者 drone CI,獲取當前分支資訊
  2. 借用 Docker 快速部署前端或者後端,根據分支資訊啟動不同的容器,並配置標籤
  3. 根據容器的標籤與當前 Git 分支對前端後端設定不同的域名

另外,這個基於容器的思路不僅僅使用於前端,同樣也適用於後端。而現實的業務中複雜多樣,如又分為已下幾種,這需要在專案的使用場景中靈活處理。

  • feature-A 的前端分支對應 feature-A 的後端分支環境
  • feature-A 的前端分支對應 develop 的後端分支環境
  • feature-A 的前端分支對應 master 的後端分支環境

相關文章