主动部署
本教程是Vue我的项目下,利用scp2主动部署到动态文件,应用cross-env跨平台地设置及应用环境变量,设置生产环境还是开发环境。
波及的配置文件:
- /deploy/*, 编译部署代码
- .env.*,我的项目环境设置文件,打包时辨别开发环境,生产环境。
- package.json中script模块,配置执行命令
一 装置
- 装置scp2:一个基于ssh2的纯JavaScript平安复制程序。它是用纯JavaScript编写的,并且能够在每个OS上运行,甚至在Windows上也能够。必须应用Nodejs(v0.8.7或更高版本)能力使其失常工作。
- 装置cross-env :这是一款运行跨平台设置和应用环境变量的脚本。NODE_ENV=production像这样设置环境变量时,大多数Windows命令提示符都会阻塞 。
npm i --save-dev scp2 cross-env
二 配置测试环境/正式环境
- 在我的项目根目录下, 创立 .env.dev 文件 (测试环境变量)
- VUE_APP_SERVER_ID变量示意 以后需部署的测试服务器ID为1
- VUE_APP_CURRENTMODE:以后测试环境
- Vue-cli3我的项目打包 生产环境和正式环境都是依照正式环境编译NODE_ENV = production
// .env.dev文件中NODE_ENV = productionVUE_APP_CURRENTMODE = developmentVUE_APP_SERVER_ID = 1
- 在我的项目根目录下, 创立 .env.prod 文件 (生产环境变量)
- VUE_APP_SERVER_ID变量示意 以后需部署的正式服务器ID为0
- VUE_APP_CURRENTMODE:以后正式环境
// .env.prod文件中NODE_ENV = productionVUE_APP_CURRENTMODE = productionVUE_APP_SERVER_ID = 0
三 配置服务器SSH远程登陆账号信息
在根目录下,创立 deploy/products.js 文件,编写服务器账号
/** 读取env环境变量*/const fs = require('fs');const path = require('path');// env 文件 判断打包环境指定对应的服务器idconst envfile = process.env.VUE_APP_CURRENTMODE === 'prod' ? '../.env.prod' : '../.env.dev';// env环境变量的门路const envPath = path.resolve(__dirname, envfile);// env对象const envObj = parse(fs.readFileSync(envPath, 'utf8'));const SERVER_ID = parseInt(envObj['VUE_APP_SERVER_ID']);function parse(src) { // 解析KEY=VAL的文件 const res = {}; src.split('\n').forEach(line => { // matching "KEY' and 'VAL' in 'KEY=VAL' // eslint-disable-next-line no-useless-escape const keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/); // matched? if (keyValueArr != null) { const key = keyValueArr[1]; let value = keyValueArr[2] || ''; // expand newlines in quoted values const len = value ? value.length : 0; if (len > 0 && value.charAt(0) === '"' && value.charAt(len - 1) === '"') { value = value.replace(/\\n/gm, '\n'); } // remove any surrounding quotes and extra spaces value = value.replace(/(^['"]|['"]$)/g, '').trim(); res[key] = value; } }); return res;}/**定义多个服务器账号 及 依据 SERVER_ID 导出以后环境服务器账号*/const SERVER_LIST = [ { id: 0, name: 'A-正式环境', "host": '******', // IP地址 "port": '80', // 服务器端口 "username": 'root', // 用户名 "password": '*******', // 明码 "path": '/home/project/landingpage/' , //服务器我的项目目录 'localfile':envObj.VUE_APP_DEV //本地打包文件名 }, { id: 1, name: 'A-生产环境', "host": '******', // IP地址 "port": '443', // 服务器端口 "username": 'root', // 用户名 "password": '******', // 明码 "path": '/home/project/landingpage/' , //服务器我的项目目录 'localfile':envObj.VUE_APP_DEV //本地打包文件名 },];module.exports = SERVER_LIST[SERVER_ID];
四 编译自动化部署脚本
在我的项目根目录下, 创立 deploy/index.js 文件.
- 先删除服务器之前的文件。避免始终上传导致冗余文件过多。
- 再上传新的文件到服务器,替换到原来的文件夹下。
问题:在文件上传的过程中,如果文件过大,上传工夫过久。会导致服务器有一段时间差打不开。
const scpClient = require('scp2');const ora = require('ora');const chalk = require('chalk');const server = require('./products');const spinner = ora( '正在公布到' + (process.env.VUE_APP_CURRENTMODE === 'prod' ? '生产' : '测试') + '服务器...');var Client = require('ssh2').Client;var conn = new Client();conn .on('ready', function() { // rm 删除dist文件,\n 是换行 换行执行 重启nginx命令 我这里是用docker重启nginx conn.exec('rm -rf '+server.path+'\ndocker restart nginx', function( err, stream ) { if (err) throw err; stream .on('close', function(code, signal) { // 在执行shell命令后,把开始上传部署我的项目代码放到这外面 spinner.start(); scpClient.scp( server.localfile, { host: server.host, // port: server.port, username: server.username, password: server.password, path: server.path }, function(err) { spinner.stop(); if (err) { console.log(chalk.red('公布失败.\n')); throw err; } else { console.log( chalk.green( 'Success! 胜利公布到' + (process.env.NODE_ENV === 'prod' ? '生产' : '测试') + '服务器! \n' ) ); } } ); conn.end(); }) .on('data', function(data) { console.log('STDOUT: ' + data); }) .stderr.on('data', function(data) { console.log('STDERR: ' + data); }); }); }) .connect({ host: server.host, // port: server.port, username: server.username, password: server.password //privateKey: require('fs').readFileSync('/home/admin/.ssh/id_dsa') });
五 增加 package.json 中的 scripts 命令, 自定义名称为 "deploy"
应用cross-env跨平台地设置及应用环境变量。公布到测试环境命令为 npm run deploy:dev,生产环境为 npm run deploy:prod
"scripts": { "serve": "vue-cli-service serve --open ", "app": "npm run serve && npm run node", "build": "vue-cli-service build", "node": "node ./server/app.js", "deploy:dev": "npm run build && cross-env VUE_APP_CURRENTMODE=dev node ./deploy", "deploy:prod": "npm run build && cross-env VUE_APP_CURRENTMODE=prod node ./deploy", "test:unit": "vue-cli-service test:unit" },
六 优化版编译自动化部署脚本:为了解决上传过程中服务器打不开的问题
先装置compressing插件,将打包文件夹压缩。
npm i compressing --save-dev
- 再将压缩文件上传服务器。
- 最初链接服务器,将原文件删除后,解压最新上传的文件。
const scpClient = require('scp2');const chalk = require('chalk');const server = require('./products');const Client = require('ssh2').Client;const ora = require('ora');var compressing = require("compressing");const environment = server.path+server.localpathconst spinner = ora('正在公布到' + environment + '服务器...');const ziping = ora('正在压缩' + environment);const conn = new Client();//压缩ziping.start()compressing.zip.compressDir( server.localpath + "/", "dist.zip") .then((e) => { ziping.stop() console.log(chalk.green('Success! 压缩胜利')); spinner.start() scpClient.scp( 'dist.zip', { host: server.host, // port: server.port, username: server.username, password: server.password, path: server.path }, (err) => { spinner.stop(); if (err) { console.log(chalk.red('公布失败.\n')); throw err; } else { conn.on('ready', () => { conn.exec('sudo unzip -o '+server.path+'dist.zip\ndocker restart nginx', (err, stream) => { if (err) throw err; stream .on('close', function(code, signal) { console.log(chalk.green('Success! 胜利公布到' + environment + '服务器! \n')); conn.end() }) }) }).connect({ host: server.host, // port: server.port, username: server.username, password: server.password //privateKey: require('fs').readFileSync('/home/admin/.ssh/id_dsa') }); } } ); }) .catch(err => { console.log(chalk.red('Fail! 压缩失败')); });
摸索学习,有什么不对的欢送指教。