一键部署项目到服务器

Caleb ... 2020-05-20
  • VuePress
  • Deploy
大约 4 分钟

提示

相对于部署到 Github Page 来说,可以使用 GitHub Actions 来进行自动部署。我们自己拥有服务器的选手,就相对来说比较麻烦。一般的情况就这些:

方法 分析
FTP FTP 的速度相对来说确实太慢了,上传东西真的是龟速
SSH 通过 SSH 直接连通服务器,大大加快了传输速度。但是还是需要手动操作数据包
宝塔面板 直接打开宝塔页面,找到指定的页面,上传文件即可。但是网速较差的情况下打会很慢

之前每次更新项目都得上传半天,很烦人。所以就着手研究怎么部署比较方便快捷。

# 设想

1.首先需要把我构建的文件夹压缩为 zip 文件。 (archiver)

2.能不能直接把压缩包从本地通过 SSH 上传到服务器。 (node-ssh)

3.上传到服务器以后怎么操作这个压缩包? (执行预留在服务器的 shell 命令)

# 上手

首先在根目录创建 deploy 文件夹,并创建config.jsindex.js

├─ deploy
│  ├─config.js
│  └─index.js
├─ docs
├─ public
1
2
3
4
5

# config.js

导出一些配置信息。

module.exports = {
	path: "/www/wwwroot/reinness.com/public.zip", //服务器上这个文件要放在哪里
	host: "xxx.xxx.xx.xx", // 服务器的host地址
	username: "xxxxxxx", // SSH用户名
	password: "xxxxxxxx", // SSH密码
	port: xx, //SSH连接的端口
};
1
2
3
4
5
6
7

# index.js

首先我们需要安装依赖插件

npm install archiver node-ssh -S
1

依赖安装完成后,导入我们需要的包









 
 
 

const path = require("path");
const archiver = require("archiver");
const fs = require("fs");
const node_ssh = require("node-ssh");
const ssh = new node_ssh();
const configs = require("./config");

const srcPath = path.resolve(__dirname, "../public");
// 为什么是"../public"?
// 因为我的项目设置的打包名称为public,而且从上面的目录树中可以了解到,public与deploy是一级。
// 所以我为了找到public文件夹,就得使用 "../public"
1
2
3
4
5
6
7
8
9
10
11

压缩目录为 public.zip























 







console.log("开始压缩dist目录...");
startZip();

function startZip() {
	var archive = archiver("zip", {
		zlib: {
			level: 8, // 搜索路径深度
		},
	}).on("error", function(err) {
		throw err; //压缩过程中如果有错误则抛出
	});
	var output = fs
		.createWriteStream(__dirname + "/public.zip")
		.on("close", function(err) {
			/*压缩结束时会触发close事件,然后才能开始上传,
              否则会上传一个内容不全且无法使用的zip包*/
			if (err) {
				console.log("关闭archiver异常:", err);
				return;
			}
			console.log("已生成zip包");
			console.log("开始上传public.zip至远程机器...");
			uploadFile();
		});

	archive.pipe(output); //典型的node流用法
	archive.directory(srcPath, "/public"); //将srcPach路径对应的内容添加到zip包中/public路径
	archive.finalize();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

上传文件到服务器

















 












function uploadFile() {
	ssh
		.connect({
			host: configs.host,
			username: configs.username,
			password: configs.password,
			port: configs.port,
		})
		.then(function() {
			console.log(configs.path);
			//上传网站的发布包至configs中配置的远程服务器的指定地址
			ssh
				.putFile(__dirname + "/public.zip", configs.path)
				.then(function(status) {
					console.log("上传文件成功");
					console.log("开始执行远端脚本");
					startRemoteShell(); //上传成功后触发远端脚本
				})
				.catch((err) => {
					console.log("文件传输异常:", err);
					process.exit(0);
				});
		})
		.catch((err) => {
			console.log("ssh连接失败:", err);
			process.exit(0);
		});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

执行远端部署脚本

具体远端部署脚本··· deploy.sh












 





function startRemoteShell() {
	// 在服务器上cwd配置的路径下执行sh deploy.sh脚本来实现发布
	ssh
		.execCommand("sh deploy.sh", {
			cwd: "/www/wwwroot/reinness.com",
		})
		.then(function(result) {
			console.log("远程STDOUT输出: " + result.stdout);
			console.log("远程STDERR输出: " + result.stderr);
			if (!result.stderr) {
				console.log("发布成功!");
				removeLocalFile();
				process.exit(0);
			}
		});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

为了不占用本地空间,完成操作后删除本地的打包文件

function removeLocalFile() {
	fs.unlink(__dirname + "/public.zip", function(error) {
		if (error) {
			console.log(error);
			return false;
		}
		console.log("删除文件成功");
	});
}
1
2
3
4
5
6
7
8
9

# deploy.sh

以我的项目为例,服务器上面的目录结构如下

├─ public
│
└─ deploy.sh
1
2
3

我的站点根节点为 public ,当上传了 public.zip 后,我需要先删除原来的 public 文件夹,然后再解压。然后删除 public.zip

rm -rf public
unzip public.zip
rm -rf public.zip
1
2
3

# 在 package.json 中添加 scripts 命令

"scripts": {
    "deploy": "node ./deploy/index.js",  // 一键发布
    "auto": "vuepress build docs && node ./deploy/index.js"  // 一键打包加发布
 }
1
2
3
4

以上所有内容供大家参考,如有问题请及时指正。

# 完结撒花🎉🎉🎉

打赏