问题
小服务上并没有Jenkins这种自动部署集成工具,也不想在服务器有限的空间里安装依赖。但是每次用sftp手动操作非常麻烦。
针对vue-cli3想想办法一键部署提高生产力。
原理
利用filemanager-webpack-plugin
在项目build
后自动生成dist的zip文件,并使用ssh2
上传zip文件并运行远程命令。
配置
修改项目根目录下的vue.config.js
const FileManagerPlugin = require('filemanager-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
// ...
module.exports = {
// ...
configureWebpack: config => {
if (isProduction) {
config.plugins.push(new FileManagerPlugin({
//初始化 filemanager-webpack-plugin plugin
onEnd: {
delete: [
// 删除在 dist 文件夹的 deploy.zip.
'./dist/deploy.zip',
],
archive: [
// 压缩 dist 后放到 dist/deploy.zip.
{source: './dist', destination: './dist/deploy.zip'},
]
}
}))
}
}
}
安装依赖:
npm i -D filemanager-webpack-plugin ssh2 readline-sync ora chalk
代码
在src目录下新建一个deploy文件夹,并新建一个index.js,自行修改对应服务器地址和静态资源文件夹。
src/deploy/index.js
const host = '<你的服务器地址>'
const WEBFOLDER = '<服务器静态资源文件夹绝对地址>';
const FILENAME = 'deploy.zip';
const readlineSync = require('readline-sync');
const ora = require('ora');
const chalk = require('chalk');
const sshClient = require('ssh2').Client;
const conn = new sshClient();
const connectingServer = ora('Connecting server...');
const sshExec = cmd => new Promise((resolve, reject) => {
conn.exec(cmd, function(
err,
stream
){
if(err) reject(err);
stream
.on('close', function(code, signal) {
resolve([code, signal]);
})
.on('data', () => {})
.stderr
.on('data', (err) => {
reject(err)
});
})
});
const shhUpload = (origin, target) => new Promise((resolve, reject) => {
const uploadingFile = ora('Uploading...');
conn.sftp(function(err, sftp) {
if (err) reject(err);
uploadingFile.start();
sftp.fastPut(
origin,
target,
{},
(err, result) => {
uploadingFile.stop();
if (err) reject(err);
if (result) console.log(result);
resolve();
}
);
});
})
readlineSync.setDefaultOptions({
encoding: 'utf8'
});
(async () => {
console.log(chalk.black.bold.bgYellow(' Server Account '));
let username = await readlineSync.question(chalk.gray.underline(' Account: '));
let password = await readlineSync.question(chalk.gray.underline(' Password: '), {
hideEchoBack: true,
});
connectingServer.start();
conn
.on('ready', async () => {
try{
console.log(chalk.green('Connected'));
connectingServer.stop();
console.log('----------------------------')
console.log(chalk.blue('Deleting old files...'));
await sshExec(`rm -rf ${WEBFOLDER}/*`);
console.log(chalk.bgGreen.black('Deleted.'));
console.log(chalk.blue('Prepare to upload zip file...'));
await shhUpload(`${__dirname}/../../dist/${FILENAME}`, `${WEBFOLDER}/${FILENAME}`)
console.log(chalk.bgGreen.black('Uploaded successfully.'));
console.log(chalk.blue('Deploying...'));
await sshExec(`unzip -o ${WEBFOLDER}/${FILENAME} -d ${WEBFOLDER}`);
console.log(chalk.blue('Removing zip file...'));
await sshExec(`rm -rf ${WEBFOLDER}/deploy.zip`);
console.log(chalk.bgGreen.black('Removed.'));
conn.end();
} catch (error) {
conn.end();
console.log(chalk.bold.bgRed.black(error));
}
})
.connect({
host,
port: 22,
username,
password,
});
})();
在项目根目录运行node src/deploy
即可运行部署脚本。
修改项目根目录package.json
,在build命令后加上 && node src/deploy
即可在build的同时自动部署到服务器。运行后会提示输入服务器用户名和密码。
...
"scripts": {
...
"build": "vue-cli-service build && node src/deploy",
...
},