告别手动拖拽上传!本教程将手把手教你如何通过ssh2-sftp-client实现Vue项目打包后自动上传到服务器,提升部署效率300%。🚀

一、需求场景与解决方案

在Vue项目开发中,每次执行npm run build后都需要手动将dist目录上传到服务器,既耗时又容易出错。通过ssh2-sftp-client库,我们可以实现:

  1. 打包完成后自动上传文件到服务器
  2. 支持覆盖更新和增量上传
  3. 保留文件权限和目录结构
  4. 部署过程可视化(进度条显示)

二、环境准备

确保你的开发环境已安装:

  • Node.js 14+
  • Vue CLI创建的项目
  • 服务器SSH连接信息(IP、用户名、密码/密钥

三、安装依赖

安装核心库和进度显示工具:

npm install ssh2-sftp-client progress --save-dev
npm install  chalk --save-dev# 或
yarn add ssh2-sftp-client progress -D

 四、安装依赖

配置package.json

  "scripts": {"dev": "vite --mode development","look": "vite --mode production","build": "vite build --mode production","preview": "vite --mode production","deploy": "node deploy.js","build:deploy": "npm run build && npm run deploy"},

  五、核心代码

在根目录上新建deploy.js 文件

import Client from 'ssh2-sftp-client';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs/promises';
import chalk from 'chalk';const server = {host: '',port: 22,username: '',password: '',remoteRoot: '/www/wwwroot'
};// 使用chalk定义颜色主题
const colors = {header: chalk.cyan.bold,success: chalk.green.bold,warning: chalk.yellow.bold,error: chalk.red.bold,file: chalk.blue,progress: chalk.magenta
};const __dirname = path.dirname(fileURLToPath(import.meta.url));
const localPath = path.resolve(__dirname, 'dist');const sftp = new Client();console.log(colors.header('🚀 开始部署操作'));
console.log(colors.header('===================='));
console.log(colors.header(`📡 连接 ${server.username}@${server.host}:${server.port}`));
console.log(colors.header(`📁 本地目录: ${localPath}`));
console.log(colors.header(`🌐 远程目录: ${server.remoteRoot}`));
console.log(colors.header('====================\n'));// 递归计算文件总数
async function getTotalFiles(dir) {const entries = await fs.readdir(dir, { withFileTypes: true });let count = 0;for (const entry of entries) {const fullPath = path.join(dir, entry.name);if (entry.isDirectory()) {count += await getTotalFiles(fullPath);} else if (entry.isFile() && !entry.name.includes('.DS_Store')) {count++;}}return count;
}sftp.connect({host: server.host,port: server.port,username: server.username,password: server.password,tryKeyboard: true
}).then(async () => {console.log(colors.success('🔑 认证成功,开始扫描本地文件...'));const totalFiles = await getTotalFiles(localPath);if (totalFiles === 0) {console.log(colors.warning('⚠️  警告: 本地目录为空,没有文件需要上传'));await sftp.end();return;}console.log(colors.success(`📊 发现 ${totalFiles} 个文件需要上传\n`));console.log(colors.header('🚚 开始上传文件:'));console.log(colors.header('------------------------------------'));let uploadedCount = 0;return sftp.uploadDir(localPath, server.remoteRoot, {ticker: (localFile) => {uploadedCount++;const relativePath = path.relative(localPath, localFile);const progress = Math.round((uploadedCount / totalFiles) * 100);console.log(colors.progress(`[${uploadedCount.toString().padStart(3, ' ')}/${totalFiles}]`) +colors.file(` ${relativePath}`) +colors.progress(` (${progress}%)`));},filter: f => !f.includes('.DS_Store')});}).then(() => {console.log('\n' + colors.success('✅ 所有文件上传完成!'));console.log(colors.success('🏁 部署成功'));sftp.end();}).catch(err => {console.error('\n' + colors.error('❌ 严重错误: ' + err.message));console.error(colors.error('🔍 失败原因分析:'));if (err.message.includes('connect')) {console.error(colors.error('- 无法连接到服务器,请检查网络'));console.error(colors.error('- 防火墙设置可能阻止了连接'));console.error(colors.error('- 服务器可能未运行SSH服务'));} else if (err.message.includes('Authentication')) {console.error(colors.error('- 用户名或密码错误'));console.error(colors.error('- 服务器可能禁用了密码登录'));console.error(colors.error('- 尝试使用SSH密钥认证'));} else if (err.message.includes('No such file')) {console.error(colors.error('- 本地文件不存在或路径错误'));console.error(colors.error('- 检查本地dist目录是否存在'));}console.error('\n' + colors.error('🛠️ 诊断命令:'));console.error(colors.error(`telnet ${server.host} ${server.port}`));console.error(colors.error(`ssh ${server.username}@${server.host}`));if (sftp) sftp.end();process.exit(1);});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91761.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91761.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91761.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《质光相济:Three.js中3D视觉的底层交互逻辑》

在Three.js搭建的虚拟维度中,光照与材质的关系远非技术参数的简单叠加,当光线以数字形态穿越虚空,与物体表面相遇的瞬间,便开始书写属于这个世界的物理叙事——每一缕光斑的形状、每一块阴影的浓淡、每一寸肌理的反光,都是对现实光学规律的转译与重构。理解这种交互的深层…

无刷电机在汽车领域的应用与驱动编程技术

文章目录引言一、核心应用场景1. 新能源汽车动力系统2. 底盘控制系统3. 车身与舒适系统4. 智能驾驶与安全系统二、无刷电机的技术优势解析三、无刷电机驱动编程基础1. 驱动原理2. 驱动架构四、核心控制算法与实现1. 六步换向法(梯形波控制)算法流程图C语…

【游戏引擎之路】登神长阶(十八):3天制作Galgame引擎《Galplayer》——无敌之道心

游戏引擎开发记录:2024年 5月20日-6月4日:攻克2D物理引擎。 2024年 6月4日-6月13日:攻克《3D数学基础》。 2024年 6月13日-6月20日:攻克《3D图形教程》。 2024年 6月21日-6月22日:攻克《Raycasting游戏教程》。 2024年…

kotlin kmp 跨平台环境使用sqldelight

欢迎访问我的主页: https://heeheeaii.github.io/ 1. 项目结构 SQLDelightKMPDemo/ ├── shared/ │ ├── src/ │ │ ├── commonMain/kotlin/ │ │ ├── androidMain/kotlin/ │ │ ├── desktopMain/kotlin/ │ │ └── commonMain/sqldel…

机器学习【五】decision_making tree

决策树是一种通过树形结构进行数据分类或回归的直观算法,其核心是通过层级决策路径模拟规则推理。主要算法包括:ID3算法基于信息熵和信息增益选择划分属性;C4.5算法改进ID3,引入增益率和剪枝技术解决多值特征偏差;CART…

简单记录一下VSCode中的一些学习记

在刚开始学习VSCode时,相信大家都会好奇VSCode底部区域那几个不同的状态栏具体有什么作用(输出、调试控制台、终端、端口),貌似好像都是输出与代码相关的信息的?貌似代码运行结果既可以出现在输出中,也可以…

基于 Hadoop 生态圈的数据仓库实践 —— OLAP 与数据可视化(二)

目录 二、Hive、SparkSQL、Impala 比较 1. SparkSQL 简介 2. Hive、SparkSQL、Impala 比较 (1)功能 (2)架构 (3)场景 3. Hive、SparkSQL、Impala 性能对比 (1)cloudera 公司…

C++:std::array vs 原生数组 vs std::vector

📌 C:std::array vs 原生数组 vs std::vector 引用: C/C 标准库 std::vector、std::array、原生静态数组 的区别有哪些? 深度剖析:std::vector 内存机制与 push_back 扩容策略 今天过去了 还有许许多个明天 能和大…

Hyper-V + Centos stream 9 搭建K8s集群(二)

一、安装自动补全主节点安装就可以yum install -y bash-completion echo source <(kubectl completion bash) >>~/.bashrc kubectl completion bash >/etc/bash_completion.d/kubectl二、安装Calico网络插件&#xff08;主节点&#xff09;下载文件wget https://ca…

VBA代码解决方案第二十七讲:禁用EXCEL工作簿右上角的关闭按钮

《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程&#xff0c;目前已经是第三版修订了。这套教程定位于入门后的提高&#xff0c;在学习这套教程过程中&#xff0c;侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码…

Spring AI 系列之三十一 - Spring AI Alibaba-基于Nacos的MCP

之前做个几个大模型的应用&#xff0c;都是使用Python语言&#xff0c;后来有一个项目使用了Java&#xff0c;并使用了Spring AI框架。随着Spring AI不断地完善&#xff0c;最近它发布了1.0正式版&#xff0c;意味着它已经能很好的作为企业级生产环境的使用。对于Java开发者来说…

sqli-labs:Less-12关卡详细解析

1. 思路&#x1f680; 本关的SQL语句为&#xff1a; $uname".$uname."; $passwd".$passwd."; $sql"SELECT username, password FROM users WHERE username($uname) and password($passwd) LIMIT 0,1";注入类型&#xff1a;字符串型&#xff0…

【SpringAI】8.通过json动态添加mcp服务

前言 官方示例的代码中&#xff0c;mcp一般是配置到yml中或者json文件中&#xff0c;使用自动装配的方式注入服务&#xff0c;这种方式不方便在程序启动后添加新的服务&#xff0c;这里参考cherry studio的方式动态添加mcp服务 1.确定方案 mcp服务的维护放到mysql业务数据库维…

【PDF + ZIP 合并器:把ZIP文件打包至PDF文件中】

B站链接 PDF ZIP 合并器&#xff1a;把ZIP文件打包至PDF文件中_哔哩哔哩_bilibiliz 加强作者的工具 https://wwgw.lanzn.com/i8h1C32k9bef 密码:30cv 新增c框架&#xff0c;加快运行速度

阿里云部署微调chatglm3

git Ifs install Git lfs 主要用于管理大型文件。在传统的Git仓库中&#xff0c;所有文件内容都会被完整记录在每一次提交中&#xff0c;这会导致仓库体积增大&#xff0c;克隆、拉取和推送操作变慢&#xff0c;甚至可能超出存储限额。Git LFS通过将大文件替换成文本指针&#…

Linux网络编程 ---五种IO模型

五种IO模型一、IO慢的原因二、五种IO模型三、如何设置非阻塞式IO&#xff1f;一、IO慢的原因 二、五种IO模型 阻塞式IO 非阻塞式IO 信号驱动IO 多路转接 异步IO 三、如何设置非阻塞式IO&#xff1f; &#xff08;一&#xff09;用法说明 &#xff08;二&#xff0…

Obsidian结合CI/CD实现自动发布

CI/CDQuickAddJS脚本bat脚本sh脚本实现自动发版Hugo文章 需求来源 每次手动执行Hugo的命令&#xff0c;手动把public文件夹上传到自己的服务器可以完成发版需求。 但是&#xff0c;作为一个内容创作者&#xff0c;我更希望的关注于自己的内容&#xff0c;而不是关注整个发版…

[硬件电路-141]:模拟电路 - 源电路,信号源与电源,能自己产生确定性波形的电路。

源电路&#xff08;Source Circuit&#xff09;是电子系统中为其他电路或负载提供特定信号或能量的基础电路模块&#xff0c;其核心功能是生成、调节或转换所需的物理量&#xff08;如电压、电流、波形、频率等&#xff09;。以下是源电路的详细解析&#xff1a;一、源电路的核…

Unity_数据持久化_PlayerPrefs基础

Unity数据持久化 一、数据持久化基础概念 1.1 什么是数据持久化 定义&#xff1a; 数据持久化就是将内存中的数据模型转换为存储模型&#xff0c;以及将存储模型转换为内存中的数据模型的统称。 通俗解释&#xff1a; 将游戏数据存储到硬盘&#xff0c;硬盘中数据读取到游戏中&…

什么是列存储(Columnar Storage)?深度解析其原理与应用场景

列存储的基本概念&#xff1a;颠覆传统的数据组织方式列存储&#xff08;Column Storage&#xff09;是一种革命性的数据库存储技术&#xff0c;它通过按列而非按行组织数据&#xff0c;从根本上改变了数据的物理存储结构。与传统行存储数据库不同&#xff0c;列式数据库将每一…