从零开始 Node实现前台自动化部署
从零开始
升级:
??现已支持增加多个配置信息,自动化部署时支持选择配置信息运行
效果展现
1. 待部署工程本地完成打包构建
本地打包构建目录
2. 确定远端部署目录及发布文件夹
远端部署目录
3. 修改配置
修改配置文件
4. 运行自动化部署
选择配置信息自动化部署
5. 查看远端效果
远端部署目录
6. 再次部署 原目录已备份(开启远端备份生效)
远端部署目录
前言
前台项目部署时,nginx配置完成后,只要将打包后的文件上传至服务器指定目录下就可。
一般使用以下方式完成:
xshell
等命令行工具上传ftp
等可视化工具上传jenkins
等自动化部署服务
对于简单前台项目,频繁部署时,xshell
、ftp
两种方式较为繁琐,而jenkins
等自动化部署服务需要提前安装软件、并熟习配置流程。
因而希望借助本地 node
服务实现对前台打包后文件的上传工作,既不需要服务器额外安装程序,还可以帮助我们实现快速上传部署,更能帮助我们深入理解 node
。
开始
1. 明确需求
进行开发前需要首先明确需求,根据常见的前台部署流程总结为以下过程:
前台部署流程
根据部署流程明确自动化部署的需求:
明确需求
2. 开发前准备
2.1 导入依赖模块
因为需要实现文件压缩、及连接远程服务器、实现远程命令调用,因而至少需要以下模块:
ssh
模块(可实现连接服务器、命令调用等常见操作)文件压缩
模块(可实现.zip
等常见压缩文件的本地打包)
查找资料,最终选择 node-ssh
和 archiver
分别实现上述功能
# 安装依赖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实现前台自动化部署