如何实现本地项目自动化部署到服务器

本文将介绍如何实现本地项目的自动化部署到服务器的过程。该过程包括以下几个步骤:打包项目、压缩打包后的文件、将压缩文件上传到服务器、在服务器上解压文件,并将解压后的文件部署到指定目录,最后清理临时文件。以下是具体的实现代码。

准备工作

首先,我们需要安装一些必要的npm包:

Terminal window
1
pnpm add node-ssh ssh2-sftp-client archiver

代码实现

以下是完整的代码实现,使用Node.js编写:

1
import { NodeSSH } from "node-ssh";
2
import fs from "fs";
3
import path from "path";
4
import archiver from "archiver";
5
import { exec } from "child_process";
6
import { fileURLToPath } from "url";
7
import Client from "ssh2-sftp-client";
8
9
const __filename = fileURLToPath(import.meta.url); // 获取文件的绝对路径
10
const __dirname = path.dirname(__filename); // 获取目录名
11
12
const ssh = new NodeSSH();
13
const sftp = new Client();
14
15
const serverConfig = {
16
host: "your server IP", // 服务器IP
17
username: "username", // 用户名
18
privateKey: "./private.pem", // 私钥
19
// 如果你使用密码登录
20
//password: "password", //
21
uploadPath: "/root/tmp/blog", // 文件上传临时目录
22
path: "/deploy/path", // 目标部署目录
23
};
24
25
async function buildProject() {
26
console.log("Building project...");
27
28
return new Promise((resolve, reject) => {
29
exec("pnpm build", (error, stdout, stderr) => {
30
if (error) {
31
console.error(`Build error: ${error.message}`);
32
return reject(error);
33
}
34
if (stderr) {
35
console.error(`Build stderr: ${stderr}`);
36
return reject(new Error(stderr));
37
}
38
console.log(`Build stdout: ${stdout}`);
39
resolve();
40
});
41
});
42
}
43
44
async function deleteLocalDist() {
45
console.log("Deleting local dist...");
46
47
return new Promise((resolve, reject) => {
48
exec("rm -rf shell/dist.zip", (error, stdout, stderr) => {
49
if (error) {
50
console.error(`Delete error: ${error.message}`);
51
return reject(error);
52
}
53
if (stderr) {
54
console.error(`Delete stderr: ${stderr}`);
55
return reject(new Error(stderr));
56
}
57
console.log(`Deleted successfully`);
58
resolve();
59
});
60
});
61
}
62
63
async function compressDist() {
64
console.log("Compressing dist directory...");
65
return new Promise((resolve, reject) => {
66
const output = fs.createWriteStream(path.join(__dirname, "dist.zip"));
67
const archive = archiver("zip", {
68
zlib: { level: 9 },
69
});
70
71
output.on("close", () => {
72
console.log(
73
`dist.zip has been created. Total bytes: ${archive.pointer()}`,
74
);
75
resolve();
76
});
77
78
archive.on("error", (err) => {
79
console.error(`Compression error: ${err.message}`);
80
reject(err);
81
});
82
83
archive.pipe(output);
84
archive.directory("dist/", true);
85
archive.finalize();
86
});
87
}
88
89
async function uploadToServer() {
90
console.log("Uploading dist.zip to server...");
91
await sftp.connect({
92
host: serverConfig.host,
93
port: 22,
94
username: serverConfig.username,
95
privateKey: fs.readFileSync(serverConfig.privateKey, "utf8"),
96
});
97
98
await sftp.put(
99
path.join(__dirname, "dist.zip"),
100
path.posix.join(serverConfig.uploadPath, "dist.zip"), // 使用 path.posix.join 处理路径
101
);
102
103
await sftp.end();
104
console.log("Upload complete.");
105
}
106
107
async function deploy() {
108
try {
109
await buildProject();
110
await compressDist();
111
await uploadToServer();
112
113
console.log("Connecting to server...");
114
await ssh.connect({
115
host: serverConfig.host,
116
username: serverConfig.username,
117
privateKey: fs.readFileSync(serverConfig.privateKey, "utf8"),
118
});
119
120
console.log("Removing old files...");
121
await ssh.execCommand(`rm -rf ${serverConfig.path}/*`);
122
123
console.log("Unzipping uploaded files...");
124
await ssh.execCommand(
125
`unzip ${serverConfig.uploadPath}/dist.zip -d ${serverConfig.uploadPath}`,
126
);
127
128
console.log("Moving files to target directory...");
129
await ssh.execCommand(
130
`mv ${serverConfig.uploadPath}/dist/* ${serverConfig.path}`,
131
);
132
133
console.log("Cleaning up...");
134
await ssh.execCommand(`rm -rf ${serverConfig.uploadPath}/dist`);
135
await ssh.execCommand(`rm ${serverConfig.uploadPath}/dist.zip`);
136
137
console.log("Deployment complete.");
138
ssh.dispose();
139
140
await deleteLocalDist();
141
} catch (error) {
142
console.error(`Deployment error: ${error.message}`);
143
ssh.dispose();
144
}
145
}
146
147
deploy();

代码解释

  1. 配置服务器信息

    • serverConfig 对象包含了服务器的IP地址、用户名、私钥路径、上传目录和目标目录。
  2. 打包项目

    • 使用 exec 函数执行 pnpm build 命令来打包项目。
  3. 压缩打包后的文件

    • 使用 archiver 模块将 dist 目录压缩成 dist.zip
  4. 上传文件到服务器

    • 使用 ssh2-sftp-client 模块将 dist.zip 上传到服务器的临时目录。
  5. 部署文件

    • 使用 node-ssh 模块连接到服务器,删除旧文件,解压上传的文件,并将文件移动到目标目录。
  6. 清理临时文件

    • 删除服务器上的临时文件和本地的 dist.zip

通过以上步骤,可以实现本地项目的自动化部署到服务器。希望本文对你有所帮助。

美团外卖红包 饿了么红包 支付宝红包