從零開始 Node實現前端自動化部署

從零開始

更新: 🎉現已支持添加多個配置信息,自動化部署時支持選擇配置信息運行前端

效果展現

1. 待部署工程本地完成打包構建vue

本地打包構建目錄

2. 肯定遠端部署目錄及發佈文件夾node

遠端部署目錄

3. 修改配置linux

修改配置文件

4. 運行自動化部署nginx

選擇配置信息

自動化部署

5. 查看遠端效果git

遠端部署目錄

6. 再次部署 原目錄已備份(開啓遠端備份生效)github

遠端部署目錄

前言

前端項目部署時,nginx配置完成後,只需將打包後的文件上傳至服務器指定目錄下便可。web

通常使用如下方式完成:vue-cli

  • xshell 等命令行工具上傳
  • ftp 等可視化工具上傳
  • jenkins 等自動化部署服務

對於簡單前端項目,頻繁部署時,xshellftp兩種方式較爲繁瑣,而jenkins 等自動化部署服務須要提早安裝軟件、並熟悉配置流程。 所以但願藉助本地 node 服務實現對前端打包後文件的上傳工做,既不須要服務器額外安裝程序,還能夠幫助咱們實現快速上傳部署,更能幫助咱們深刻了解 nodeshell

PS: 以前一直在準備相關前端自動化部署的實現,最近恰好看到 笪笪 的文章,參考文章中說起的 node-ssharchiver ,完成對該項目的實現, 在此表示感謝(同時感謝 node-ssharchiverinquirer 做者)。

附:npm地址

開始

1. 明確需求

進行開發前須要首先明確需求,根據常見的前端部署流程總結爲如下過程:

前端部署流程

根據部署流程明確自動化部署的需求:

明確需求

2. 開發前準備

2.1 導入依賴模塊

因爲須要實現文件壓縮、及鏈接遠程服務器、實現遠程命令調用,所以至少須要如下模塊:

  • ssh 模塊(可實現鏈接服務器、命令調用等常見操做)
  • 文件壓縮 模塊(可實現 .zip 等常見壓縮文件的本地打包)
  • 命令行選擇 模塊(可實現對多配置項文件進行選擇和使用)

查找資料,最終選擇 node-ssharchiverinquirer 分別實現上述功能。

# 安裝依賴
npm i node-ssh --save
npm i archiver --save
npm i inquirer --save
複製代碼

2.2 如何實現規範

爲實現需求中的 解耦合理邏輯清晰/靈活 ,須要關注總體程序邏輯,這裏選擇 封裝 相關功能實現,並在 主程序 中自由調度(可靈活 調用/關閉/修改 相關功能),並對於當前所執行功能給與提示,以保證功能實現的 完整性異常提示

由於 文件壓縮文件上傳執行遠端命令 等存在異步過程,所以須要明確功能完成的順序,即 應在前置任務完成的回調中開啓當前任務,爲實現控制異步過程和代碼邏輯清晰,這裏選擇使用 ES6 的 Promise 結合 ES7的語法糖 async awiat 實現邏輯流程控制。

到這裏就完成了對程序功能構建的梳理工做,下面進入項目實現。

3. 功能實現

工程目錄預覽 這裏先展現最終結果的工程目錄,以供參考:

工程目錄

  • node_modules
  • utils
    • compressFile.js【壓縮本地文件】
    • handleCommand.js【調用遠端命令】
    • helper.js【】
    • ssh.js【鏈接遠端務器】
    • uploadFile.js【上傳本地文件】
  • app.js【主程序】
  • config.js【配置文件】
  • dist.zip【壓縮後的文件】(當前版本不會自動刪除)
  • package.json
  • README.md【項目介紹】

3.1 壓縮本地文件

compressFile 接收 須要壓縮的目錄打包生成文件,傳入後實現本地文件壓縮。

compressFile.js 參考代碼

// compressFile.js
var fs = require('fs')
var archiver = require('archiver')

function compressFile (targetDir, localFile) {
  return new Promise((resolve, reject)=>{
    console.log('1-正在壓縮文件...')
    let output = fs.createWriteStream(localFile) // 建立文件寫入流
    const archive = archiver('zip', {
      zlib: { level: 9 } // 設置壓縮等級
    })
    output.on('close', () => {
      resolve(
        console.log('2-壓縮完成!共計 ' + (archive.pointer() / 1024 /1024).toFixed(3) + 'MB')
      )
    }).on('error', (err) => {
      reject(console.error('壓縮失敗', err))
    })
    archive.pipe(output) // 管道存檔數據到文件
    archive.directory(targetDir, 'dist') // 存儲目標文件並重命名
    archive.finalize() // 完成文件追加 確保寫入流完成
  })
}

module.exports = compressFile
複製代碼

3.2 鏈接遠端服務器

connectServe 接收遠端ip用戶名密碼等信息,完成遠端服務器鏈接,具體配置參考 config.js

ssh.js 參考代碼

// ssh.js
node_ssh = require('node-ssh')
ssh = new node_ssh()

function connectServe (sshInfo) {
  return new Promise((resolve, reject) => {
    ssh.connect({ ...sshInfo }).then(() => {
      resolve(console.log('3-' + sshInfo.host + ' 鏈接成功'))
    }).catch((err) => {
      reject(console.error('3-' + sshInfo.host + ' 鏈接失敗', err))
    })
  })
}

module.exports = connectServe
複製代碼

3.3 遠端執行命令

runCommand 接收 需執行的命令執行命令的遠端路徑,這裏將其單獨拆分,既方便 主程序 的單獨調用,也方便 文件上傳 等功能的模塊封裝,達到 解耦 的效果。

handleCommand.js 參考代碼

// handleCommand.js
node_ssh = require('node-ssh')
ssh = new node_ssh()

// run linux shell
function runCommand (command, path) {
  return new Promise((resolve, reject) => {
    ssh.execCommand(command, {
      cwd: path
    }).then((res) => {
      if (res.stderr) {
        reject(console.error('發生錯誤:' + res.stderr))
      } else {
        resolve(console.log(command + ' 執行完成!'))
      }
    })
  })
}

module.exports = runCommand
複製代碼

3.4 文件上傳

uploadFile 接收 系統配置參數待上傳的本地文件 ,完成本地文件上傳至指定服務器目錄,這裏還引入 handleCommand.js ,根據 openBackUp 是否開啓遠端備份,完成對存在解壓後同名目錄的處理。具體配置參考 config.js

uploadFile.js 參考代碼

// uploadFile.js
node_ssh = require('node-ssh')
ssh = new node_ssh()
runCommand = require ('./handleCommand')

async function uploadFile (config, localFile) {
  return new Promise((resolve, reject) => {
    console.log('4-開始文件上傳')
    handleSourceFile()
    ssh.putFile(localFile, config.deployDir + config.targetFile).then(async () => {
      resolve(console.log('5-文件上傳完成'))
    }, (err) => {
      reject(console.error('5-上傳失敗!', err))
    })
  })
}

// 處理源文件
async function handleSourceFile () {
  if (config.openBackUp) {
    console.log('已開啓遠端備份!')
    await runCommand(
      ` if [ -d ${config.releaseDir} ]; then mv ${config.releaseDir} ${config.releaseDir}_${new Date().getTime()} fi `,
      config.deployDir)
  } else {
    console.log('提醒:未開啓遠端備份!')
    await runCommand(
      ` if [ -d ${config.releaseDir} ]; then mv ${config.releaseDir} /tmp/${config.releaseDir}_${new Date().getTime()} fi `,
      config.deployDir)
  }
}

module.exports = uploadFile
複製代碼

3.5 主程序

當全部功能模塊封裝完成後,其中 異步流程 均使用 Promise 處理,這時結合 async awiat 實現,既保證了功能實現的順序,也使得功能組合變得更加簡潔、優雅。

main 函數中通關功能組合實現自動化部署的流程,後續增長其餘功能實現,主程序 中引入、組合便可完成升級。

app.js 參考代碼

// app.js
config = require ('./config')
compressFile = require ('./utils/compressFile')
connectServe = require ('./utils/ssh')
uploadFile = require ('./utils/uploadFile')
runCommand = require ('./utils/handleCommand')

// 可單獨執行
async function main () {
  const localFile =  __dirname + '/' + config.targetFile
  config.openCompress ? await compressFile(config.targetDir, localFile) : '' //壓縮
  await connectServe(config.ssh) // 鏈接
  await uploadFile(config, localFile) // 上傳
  await runCommand('unzip ' + config.targetFile, config.deployDir) // 解壓
  await runCommand('mv dist ' + config.releaseDir, config.deployDir) // 修改文件名稱
  await runCommand('rm -f ' + config.targetFile, config.deployDir) // 刪除
  console.log('全部操做完成!')
  process.exit()
}
// run main
main()
複製代碼

3.6 配置文件

爲方便前端自動化部署,這裏抽離關鍵信息,生成配置文件。 用戶只需修改配置文件便可實現 自動化部署

config.js 參考代碼

// config.js
/* 說明: 請確保解壓後的文件目錄爲dist ssh: 鏈接服務器用戶信息 targetDir: 須要壓縮的文件目錄(需開啓壓縮) targetFile: 指定上傳文件名稱(該文件同級目錄) openCompress: 關閉後,將跳過目標目錄壓縮步驟,直接上傳指定文件 openBackUp: 開啓後,若遠端存在相同目錄,則會修改原始目錄名稱,不會直接覆蓋 deployDir: 指定遠端部署地址 releaseDir: 指定遠端部署地址下的發佈目錄名稱 */

const config = {
  ssh: {
    host: '192.168.0.110',
    username: 'root',
    password: 'root'
  },
  targetDir: 'E:/private/my-vue-cli/dist', // 目標壓縮目錄(可以使用相對地址)
  targetFile: 'dist.zip', // 目標文件
  openCompress: true, // 是否開啓壓縮
  openBackUp: true, // 是否開啓遠端備份
  deployDir: '/home/node_test' + '/', // 遠端目錄
  releaseDir: 'web' // 發佈目錄
}

module.exports = config
複製代碼

使用

拉取源碼、安裝依賴、修改配置文件、運行便可

npm install
npm run deploy
複製代碼

🎉該項目已開源至 github 歡迎下載使用 後續會完善更多功能 🎉 源碼及項目說明 Tip: 喜歡的話別忘記 star 哦😘,有疑問🧐歡迎提出 issues ,積極交流。

個人簡書

相關文章
相關標籤/搜索