天天看點

基于 vue-cli 的前端項目的自動釋出預覽環境場景實施改進總結

場景

進入公司一段時間了。流程還是不太讓人省心。就在上個提測版本的品質還是沒法保證,總是或多或少出現一些問題。于是就想到了上家公司的一個做法。就是在提測前部署一個預覽環境,在提測前,每個人本地驗證一遍,再放在預覽環境驗證一遍。

實施

有了想法,就得去付諸行動。先是用公司的一個測試伺服器單獨起了一個服務,用nginx來做反向代理。然後把前端代碼部署上去。

整個部署流程是:用 xshell 連上伺服器,然後用 xftp 連結伺服器,然後本地 build 項目,接着把 build 好的檔案通過 xftp 上傳到伺服器上。整個流程感覺稍有繁瑣。而且,對于不熟悉 shell 工具的同學不友好啊。重複的工作啊有沒有。

改進

既然前端是萬能的,那麼這種重複的操作在我們前端工作流中是不被允許的。剛好項目進度不是那麼忙。于是就準備啪啪啪撸一個 build 完成自動釋出預覽環境的工具。

要完成這個工具,我們來梳理一下需要實作的功能:

  • 本地檔案壓縮功能
  • 連結遠端伺服器
  • 壓縮包上傳遠端伺服器
  • 遠端伺服器解壓縮
  • 本地 build 完畢的一個回調

可能你會說,你傻啊,不會直接上傳,還要壓縮解壓縮。這裡用壓縮包傳輸一方面是友善做備份。我考慮的是上傳在一個backup的檔案夾裡,然後用的時候再從這個檔案夾取出來,然後解壓到置頂目錄。提測的時候也可以直接讓測試來這個目錄去壓縮包。

另一方面是不想寫遞歸啊。如果要上傳的目錄結構不确定少不了遞歸啊,遞歸啊,遞歸啊。我怕我頭大。

本地檔案壓縮

于是建立一個 ftp.js 的檔案,來實作上傳本地 build 完的 dist 目錄下的檔案到伺服器。

基于 vue-cli 的前端項目的自動釋出預覽環境場景實施改進總結

這裡主要使用了 archiver 這個子產品來實作壓縮功能。

用 archiver 壓縮本地檔案:

let output = fs.createWriteStream(__dirname + '/../dist/' + fileName);
let archive = archiver('zip');
output.on('end', function () {
  console.log('Data has been drained');
});
output.on('error', function (err) {
  console.log('壓縮失敗');
  throw err;
});
output.on('close', function () {
  console.log('壓縮成功');
});
archive.pipe(output);
archive.file(__dirname + '/../dist/index.html', {name: 'index.html'});
archive.directory(__dirname + '/../dist/static/', 'static');
archive.finalize();
           

fileName 是一個加戳的變量:

let fileName = 'dist' + new Date().getTime() + '.zip';
           

說道這裡,其實還可以把 git 的分支或者 tag 資訊放在這個戳裡邊。用相關的 nodejs 子產品來擷取一下 git 倉庫資訊就好啦。有空我要來優化一波。

連結遠端伺服器和上傳檔案。

主要使用了 ssh2 這個子產品來實作和遠端伺服器的互動。

連結遠端伺服器:

conn.on('ready', function () {
  console.log('連接配接上了!')  
}).on('end', function () {
  console.log('完成')
}).connect({
  host: 'ip',
  port: 端口号,
  username: '使用者名',
  password: '密碼'
});
           

上傳檔案:

conn.sftp(function (err, sftp) {
  if (err) throw err;
  // 上傳檔案測試
  sftp.fastPut(__dirname + '/../dist/' + fileName, '/usr/share/nginx/htmlBackup/' + fileName, {}, (err, result) => {
    if (err) {
      console.log(err);
    }
    if (result) console.log(result);
  });
});
           

删除上個版本解壓縮部署新版本

本來,使用 ssh2 的 shell 指令來實作這兩個功能應該是很簡單的。可是,沒逼格啊。麻煩啊。于是我就想到 shell 腳本。說實話,在此之前,我也不知道 shell 腳本咋玩滴。但是我可以學嘛。于是,學習一波後就有了如下 html.sh 檔案:

#!/bin/bash
# arg1:dir name  
# arg2:zip name
# delete old file 
deleteFile=$1
sudo chmod -R 777 /usr/share/nginx/$deleteFile
sudo rm -rf /usr/share/nginx/$deleteFile/*
# unzip file 
unzipFile=$2
sudo unzip -o /usr/share/nginx/htmlBackup/$unzipFile -d /usr/share/nginx/$deleteFile
# exit
           

其實 shell 腳本也不算複雜,大概一上午吧,寫了這麼幾行。伺服器權限設定有點嚴格,是以先用 chmod 給老檔案設定權限,我懶于是就用 777 。然後,rm 删除老檔案,然後解壓縮 zip 包。其中 $1 和 $2 是調用這個 shell 傳入的參數。

好了,說了這麼多,shell 怎麼用。當然還是要回到 ssh2 上。代碼如下:

// 調用遠端建構shell
conn.exec('/usr/share/nginx/html.sh html ' + fileName, function(err, stream) {
  if (err) throw err;
  stream.on('close', function(code, signal) {
    console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
    conn.end();
  }).on('data', function(data) {
    let dataStr = ('' + data).trim();
    // 列出已經上傳過的 zip 包
    if (dataStr.length > 5) {
      console.log('STDOUT: ' + ('' + data).trim());
    }
  }).stderr.on('data', function(data) {
    console.log('STDERR: ' + ('' + data).trim());
  });
  stream.on('end', function() {
    console.log('預覽環境建構完成');
  });
});
           

新增功能基本上大功告成了。

build 回調

首先找到 vue-cli build 完成後的位置,也就是 build/build.js 配置中大概40行的位置。然後把上邊我們寫的功能導出子產品,然後再 build.js 中引入 ftp.js。

let ftp = require('./ftp')
           

注意,這裡我并不想破壞原有的指令的功能,于是就通過判斷執行指令時的參數來控制功能的啟用與否。

process.argv

這個變量存放的就是調用指令的參數。具體是什麼用的,console.log 一下就都知道啦。

于是就有了下圖:

基于 vue-cli 的前端項目的自動釋出預覽環境場景實施改進總結

那麼指令輸入長了,敲字手疼啊。于是就修改 package.json 的 scripts。

添加如下兩行:

"bap": "node build/build.js buildWithPublish",
"p": "node build/ftp.js publish"
           

這樣,我們使用的時候就可以直接 npm run bap 來 build 和 釋出預覽環境。用 npm run p 來直接把已經 build 好的檔案釋出到預覽環境。

基于 vue-cli 的前端項目的自動釋出預覽環境場景實施改進總結

總結

好吧,作為一個能用即可的懶人,代碼寫的有點亂,整個功能的代碼就不貼啦。基本上核心功能的代碼就是上述說的那些。

避免重複就是節約時間啊。用了大概一天時間來實作這個功能我覺得很值。這樣以後組裡的其他同僚也都可以用一行指令自己部署預覽環境了。不用打開 xshell 打開 xftp。

基于上述功能,還做了一個提測小工具:https://segmentfault.com/a/11...

繼續閱讀