我們這邊好多小組覺得每次測試人員叫我們開發打包部署到某某個測試環境人工操作比較麻煩,因為他們想做到只專注於開發,不管這些瑣碎的事。於是有個組長問我前端能不能用Jenkins去執行這一個固定的流程,因為他們后端都是用Jenkins去實現自動化打包部署。我之前沒用過Jenkins,於是我去Jenkins官網看了下,發現確實是可以使用Jenkins實現前端自動化打包部署的,因為Jenkins可以執行遠程shell腳本,我們開發是在Windows下,只是相當於在Linux下打包而已,而前端項目完全是可以在Linux環境下打包的。(順便提一句,我們的Jenkins部署在CentOS下,所以以下示例代碼均以CentOS環境為例,示例中的Jenkins語言文字漢化不完整,不過大家按圖索驥應該也能找到相應的位置)
1.安裝nodejs,publish over ssh插件
打開Jenkins首頁->Manage Jenkins->Manage Plugins
這里有兩種安裝方式,一種是聯網直接在“可安裝”這個tab頁中搜索安裝;還有一種是離線安裝。由於我們處於內網,所以我用了第二種方式離線安裝,此處以離線安裝nodejs插件為例。Jenkins插件地址:https://plugins.jenkins.io
然后你就會獲得一個名為nodejs.hpi的離線插件。然后通過“高級”這個tab頁里的上傳插件功能導入這個插件即可。
安裝好插件之后需要重啟Jenkins,只要在Jenkins的url后添加/restart回車稍等幾分鍾即可。
2.在jenkins所在的Linux主機上安裝node.js並配置環境變量。
下載node.js的release包,推薦清華大學開源軟件鏡像網:https://mirrors.tuna.tsinghua.edu.cn/nodejs-release/,要不牆的你懷疑人生。找到你想要的node版本,查看Linux架構可用arch命令,如下圖所示,x64就是x86_64的簡稱,此處以下載最新版node為例,一般不推薦最新版,容易出各種莫名其妙的bug,最好和開發node版本一樣,然后點擊下載。
這里建議再安裝一個node-sass的release包,因為每次前端npm install出問題有一半原因都是因為node-sass安裝出問題,而且內網也沒聯網,這里我也就一起離線安裝了。這個node-sass版本需要與node版本相匹配,否則會報錯,具體可以參考我這篇文章https://www.cnblogs.com/jdWu-d/p/13594721.html。如果覺得自己npm install沒啥問題就可以跳過不用看了。
然后將這兩個release包上傳到服務器的某個目錄下,我以某個用戶下新建的node文件目錄存放release包,以某用戶下.bash_profile配置局部環境變量為例,如需全局環境變量,可到etc/profile配置。
在.bash_profile文件下添加
export PATH=/nodejs的release包所在路徑/bin:$PATH
export SASS_BINARY_PATH=/node-sass的release包所在路徑 //如無離線安裝node-sass,則可不配置
添加完畢后保存退出編輯,然后用source .bash_profile命令刷新局部變量。然后node -v測試是否安裝成功
3.jenkins系統配置和全局工具配置
(1)打開Jenkins首頁->Manage Jenkins->Configure System->全局屬性->Environment variables->新增鍵值隊列表,如果不設置此項,會導致Jenkins內部無法識別node及npm等命令,最后在執行npm run build的時候會報錯:npm:未找到命令。
Linux查看PATH命令為echo $PATH
為了方便,我直接把所有PATH直接添加進去,大家自己可以按需添加,SASS_BINARY_PATH如無離線安裝node-sass則無必要添加
(2)打開Jenkins首頁->Manage Jenkins->Global Tool Configure->nodejs安裝,別名隨便取,安裝目錄填nodejs的release包所在路徑,然后保存
4.寫測試腳本
此步驟只是為了驗證上述的配置是否生效,自信的可以直接跳過此步驟查看步驟5
打開Jenkins首頁->new item->Freestyle Project
在構建環境中勾選“Provide Node&npm bin/folder to PATH”選擇步驟3中nodejs安裝填寫的那個別名,測試語句node -v & npm -v。然后保存。
在項目列表,右鍵Build Now。
在構建歷史中查看,看到藍色即成功,紅色即失敗,點擊進入詳情頁面,查看控制台輸出,看見有輸出node和npm的版本,則證明上述配置生效。
5.添加憑據
打開Jenkins首頁->憑據->系統->全局憑據->添加憑據,分別添加github及目標主機的賬戶密碼,注意,其中ID是唯一且不可修改的。這些ID將會與步驟6腳本中的credentialsId(“examples”,“172.XXX.XXX.XXX”)相對應,否則會報錯。
6.寫流水線腳本
建立一個流水線項目,打開Jenkins首頁->new item->流水線,在腳本中填寫代碼下載->打包->部署流程的腳本代碼。
流水線語法有兩種,一種是聲明式語法,一種是腳本式語法,官方文檔手冊傳送門:https://www.jenkins.io/zh/doc/book/pipeline/syntax/。這里以腳本式語法為例,具體代碼如下:
node("master"){ //清理工作區 step([$class:'WsCleanup']) //工程部署目標服務器ip def deploy_ip='172.XXX.XXX.XXX' //目標服務器dist包所在目標目錄 def path='/home/XXXX/nginx/html' //當前日期 def cur_date="`date + %Y%m%d`" stage('代碼下載'){ checkout([$class:'GitSCM',branches: [[name:'*/test']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [],userRemoteConfigs: [[credentialsId: 'examples', url: 'http://172.XXX.XXX.XXX/XXX/XXX.git']]]) } stage('打包代碼'){ sh ''' cd /home/XXX/.jenkins/workspace/fronted_build_test npm install #此處也可用unzip node_modules.zip,詳見下方解釋 chmod -R 755 ./* npm run build & sleep 1m mv dist distJenkinsTest #也可以在vue.config.js里的outputDir里自己設置包名 ''' } withCredentials([usernamePassword(credentialsId: '172.XXX.XXX.XXX', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]){ stage('部署dist包'){ //創建必要的文件夾 sh "sshpass -p '$PASSWORD' ssh -o StrictHostKeyChecking=no $USERNAME@$deploy_ip \" if [ ! -d $path/backup ]; then mkdir $path/backup; fi\" " //備份舊dist文件 sh "sshpass -p '$PASSWORD' ssh -o StrictHostKeyChecking=no $USERNAME@$deploy_ip \" if [ -d $path/distJenkinsTest ]; then mv $path/distJenkinsTest/ $path/backup/distJenkinsTest-$cur_date; fi\" " //將新dist包上傳到目標服務器目標目錄 sh "sshpass -p '$PASSWORD' scp -r distJenkinsTest $USERNAME@$deploy_ip:$path " } }
打包代碼中,我還是建議可以第一次構建可以npm install,然后在workspace里把npm install后生成的node_modules文件壓縮成node_modules.zip,之后可以使用unzip node_modules.zip,因為只要項目中不引入新的模塊和插件node_modules文件夾內的內容是不會變的,沒必要每次都npm install,經常npm install不僅考驗網速,而且還容易報錯。Linux下壓縮node_modules文件夾請用命令zip -r -y node_modules.zip node_modules/,因為node_modules文件夾里有很多符號鏈接,沒有使用”-y“參數會導致npm run build打包的時候這文件找不到那文件找不到,這模塊丟失那模塊丟失。
至此,就可以一勞永逸的使用Jenkins實現前端的自動化打包部署了,你也不會在群里看見測試@你的名字喊你部署包到哪個環境了