搞了一个服务器准备折腾一下,但是每次打包用FTP一个个传文件太麻烦了。 受不了于是准备搞个脚本自动部署下。
于是乎,我今天教你配一套自动化部署脚本 ,以后改完代码直接一个命令npm run deploy,喝杯咖啡十分钟的功夫,就自动打包部署完了。
第一步:配置免密登录
让本地电脑和服务器之间建立信任关系,不然每次上传都要输密码,烦都烦死。
本地生成密钥(如果你之前没搞过的话):
bash
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"
一路回车就行。这就像给你的电脑办了张身份证。
查看刚生成的密钥:
bash
cat ~/.ssh/id_rsa.pub
会出来一长串字符,全选复制它!这是你电脑的"身份证号"。
登录服务器添加信任:
bash
ssh username@your-server-ip
输完密码进去后,执行下面这几条命令:
bash
# 创建存放密钥的文件夹
mkdir -p ~/.ssh
# 设置文件夹权限
chmod 700 ~/.ssh
# 把刚才复制的公钥粘贴进去
echo "粘贴你刚才复制的那一长串" >> ~/.ssh/authorized_keys
# 设置密钥文件权限
chmod 600 ~/.ssh/authorized_keys
测试一下有没有配好 :退出服务器后重新执行
ssh username@your-server-ip,如果不用输密码直接进去了,那就成了!
第二步:部署脚本
在项目根目录新建一个deploy。js文件,直接把下面代码复制进去:
javascript
// deploy.js - 完整的部署脚本(直接上传文件版本)
import { execSync } from 'child_process'
import fs from 'fs'
import path from 'path'
// 配置信息 - 根据你的实际情况修改
const config = {
server: 'username@your-server-ip', // 替换为你的服务器信息
deployPath: 'yourpath'
}
// 彩色日志
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m'
}
function log(message, color = colors.reset) {
console.log(color + message + colors.reset)
}
function runCommand(command, description) {
log(`📝 ${description}`, colors.blue)
log(` 执行: ${command}`, colors.yellow)
try {
const output = execSync(command, { stdio: 'inherit' })
log(`✅ ${description} 成功`, colors.green)
return true
} catch (error) {
log(`❌ ${description} 失败: ${error.message}`, colors.red)
return false
}
}
// 递归获取目录中的所有文件
function getAllFiles(dirPath, arrayOfFiles = []) {
const files = fs.readdirSync(dirPath)
files.forEach((file) => {
const fullPath = path.join(dirPath, file)
if (fs.statSync(fullPath).isDirectory()) {
arrayOfFiles = getAllFiles(fullPath, arrayOfFiles)
} else {
arrayOfFiles.push(fullPath)
}
})
return arrayOfFiles
}
// 主部署函数
async function deploy() {
log('🚀 开始直接文件上传部署流程', colors.blue)
log('='.repeat(50))
// 1. 检查 dist 目录是否存在,如果不存在则构建
if (!fs.existsSync('dist')) {
log('📦 dist 目录不存在,开始构建项目...', colors.yellow)
if (!runCommand('npm run build', '项目构建')) {
return
}
} else {
log('📦 发现已存在的 dist 目录,跳过构建', colors.green)
}
// 2. 获取 dist 目录中的所有文件
log('📋 扫描 dist 目录中的文件...', colors.blue)
const distFiles = getAllFiles('dist')
log(`📄 找到 ${distFiles.length} 个文件需要上传`, colors.green)
// 3. 测试服务器连接
log('🔗 测试服务器连接...', colors.blue);
if (!runCommand(`ssh -o ConnectTimeout=10 ${config.server} "echo '连接成功'; exit"`, '测试SSH连接')) {
return;
}
// 4. 在服务器上创建备份
log('💾 在服务器上创建备份...', colors.blue);
const backupCommands = `set -e; cd ${config.deployPath}; echo "备份当前文件..."; if [ -f "index.html" ] || [ -d "assets" ]; then tar -czf backup_old.tar.gz index.html assets 2>/dev/null || true; echo "✅ 当前文件已备份为 backup_old.tar.gz"; else echo "⚠️ 没有找到当前文件,跳过备份"; fi; echo "清理旧文件..."; rm -rf index.html assets; echo "✅ 服务器准备完成"; exit 0`;
if (!runCommand(`ssh -o ConnectTimeout=30 ${config.server} "${backupCommands}"`, '服务器准备')) {
return;
}
// 5. 逐个上传文件到服务器
log('📤 开始上传文件到服务器...', colors.blue)
let uploadedCount = 0
for (const filePath of distFiles) {
const relativePath = path.relative('dist', filePath)
const remotePath = path
.join(config.deployPath, relativePath)
.replace(/\\/g, '/')
const remoteDir = path.dirname(remotePath).replace(/\\/g, '/')
// 确保远程目录存在
const mkdirCommand = `ssh ${config.server} "mkdir -p ${remoteDir}"`
if (!runCommand(mkdirCommand, `创建目录: ${remoteDir}`)) {
continue
}
// 上传文件
const scpCommand = `scp ${filePath} ${config.server}:${remotePath}`
if (runCommand(scpCommand, `上传文件: ${relativePath}`)) {
uploadedCount++
}
}
log(
`✅ 文件上传完成: ${uploadedCount}/${distFiles.length} 个文件`,
colors.green
)
// 6. 在服务器上设置文件权限
log('🔒 设置服务器文件权限...', colors.blue);
const permissionCommands = `set -e; cd ${config.deployPath}; echo "设置文件权限..."; chmod -R 755 .; echo "✅ 权限设置完成"; exit 0`;
runCommand(`ssh -o ConnectTimeout=30 ${config.server} "${permissionCommands}"`, '设置文件权限');
// 7. 验证部署
log('🔍 验证部署结果...', colors.blue);
runCommand(
`ssh -o ConnectTimeout=10 ${config.server} "cd ${config.deployPath} && ls -la && echo '--- 文件统计 ---' && find . -type f | wc -l; exit"`,
'检查部署目录'
);
log('\n🎉 部署完成!', colors.green)
log(`🌐 请访问: http://${config.server.split('@')[1]}`, colors.green)
log('='.repeat(50))
}
// 执行部署
deploy().catch((error) => {
log(`💥 部署过程出现错误: ${error.message}`, colors.red)
process.exit(1)
})
这脚本干了啥?
- 自动检查有没有打包文件,没有就先打包
- 测试服务器连接(别传到一半断了)
- 备份服务器上的旧文件(万一新版本有问题能回滚)
- 上传所有新文件
- 设置好权限让Nginx能访问
第三步:配置打包命令
打开package.json,在scripts里加一行:
json
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"deploy": "vite build && node deploy.js"
},
就这么简单!
开始享受一键部署
以后每次改完代码需要部署的时候,终端里输入:
bash
npm run deploy
然后你就会看到彩色的日志在跑,打包→上传→部署 一气呵成。等出现🎉 部署完成!的时候,刷新浏览器就能看到新版本了。没看到记得重启一下nginx。
是不是超简单?
以后再也不用打开一堆工具手动传文件了,改完代码一个命令搞定,省下的时间够你多摸几次鱼了。