从零开始 Node实现前台自动化部署

作者 : 开心源码 本文共5028个字,预计阅读时间需要13分钟 发布时间: 2022-05-13 共153人阅读

从零开始

升级:
??现已支持增加多个配置信息,自动化部署时支持选择配置信息运行

效果展现

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

本地打包构建目录

2. 确定远端部署目录及发布文件夹

远端部署目录

3. 修改配置

修改配置文件

4. 运行自动化部署

选择配置信息自动化部署

5. 查看远端效果

远端部署目录

6. 再次部署 原目录已备份(开启远端备份生效)

远端部署目录

前言

前台项目部署时,nginx配置完成后,只要将打包后的文件上传至服务器指定目录下就可。

一般使用以下方式完成:

  • xshell 等命令行工具上传
  • ftp 等可视化工具上传
  • jenkins 等自动化部署服务

对于简单前台项目,频繁部署时,xshellftp两种方式较为繁琐,而jenkins 等自动化部署服务需要提前安装软件、并熟习配置流程。
因而希望借助本地 node 服务实现对前台打包后文件的上传工作,既不需要服务器额外安装程序,还可以帮助我们实现快速上传部署,更能帮助我们深入理解 node

开始

1. 明确需求

进行开发前需要首先明确需求,根据常见的前台部署流程总结为以下过程:

前台部署流程

根据部署流程明确自动化部署的需求:

明确需求

2. 开发前准备

2.1 导入依赖模块

因为需要实现文件压缩、及连接远程服务器、实现远程命令调用,因而至少需要以下模块:

  • ssh 模块(可实现连接服务器、命令调用等常见操作)
  • 文件压缩 模块(可实现 .zip 等常见压缩文件的本地打包)

查找资料,最终选择 node-ssharchiver 分别实现上述功能

# 安装依赖npm i node-ssh --savenpm i archiver --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.jsvar 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.jsnode_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.jsnode_ssh = require('node-ssh')ssh = new node_ssh()// run linux shellfunction 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.jsnode_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.jsconfig = 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 mainmain()

3.5 配置文件

为方便前台自动化部署,这里抽离关键信息,生成配置文件。
客户只要修改配置文件就可实现 自动化部署

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 installnpm run deploy

??该项目已开源至 github 欢迎下载使用 后续会完善更多功能 ??
源码及项目说明
Tip: 喜欢的话别不记得 star 哦??,有疑问??欢迎提出 issues ,积极交流。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 从零开始 Node实现前台自动化部署

发表回复