前端自动化部署服务器, 告别繁琐部署过程

2019-11-14 admin

永恒的前言


简单实用的前端部署, 一条命令搞定, 省去繁琐的步骤! 主要是 nodejs shelljs(命令行命令) node-ssh(连接服务器) 项目git 地址 (这个git项目是我自己搭的一个比较low的vue脚手架,集成ts) (主要看 自动部署 在 upload 目录 )

如何在你项目中使用( 五步曲 )

第一步, 把项目里 upload 文件夹复制到你项目根目录

image.png

第二步, 下载该js相关依赖 npm 或 cnpm i chalk ora shelljs node-ssh inquirer compressing -D

第三步, 打开 upload/config.js 配置文件, 配置ssh地址, 用户名, 验证方式,需要上传的目录

image.png

第四步, 在你项目中 package.json 文件中 加上 “deploy”: “node ./upload/upload.js”

image.png

最后 在命令行输入 npm run deploy 选择发布环境 然后就ojbk了

image.png image.png image.png image.png

大功告成–


来看主要文件 upload.js

首先项目依赖

const chalk = require('chalk') //命令行颜色
const ora = require('ora') // 加载流程动画
const spinner_style = require('./spinner_style') //加载动画样式
const shell = require('shelljs') // 执行shell命令
const node_ssh = require('node-ssh') // ssh连接服务器
const inquirer = require('inquirer') //命令行交互
const zipFile = require('compressing')// 压缩zip
const fs = require('fs') // nodejs内置文件模块
const path = require('path') // nodejs内置路径模块
const CONFIG = require('./config') // 配置

一些常量,变量和logs

const SSH = new node_ssh();
let config; // 用于保存 inquirer 命令行交互后选择正式|测试版的配置

//logs
const defaultLog = log => console.log(chalk.blue(`---------------- ${log} ----------------`));
const errorLog = log => console.log(chalk.red(`---------------- ${log} ----------------`));
const successLog = log => console.log(chalk.green(`---------------- ${log} ----------------`));

//文件夹目录
const distDir = path.resolve(__dirname, '../dist'); //待打包
const distZipPath = path.resolve(__dirname, `../dist.zip`);
//打包后地址(dist.zip是文件名,不需要更改, 主要在config中配置 PATH 即可)

首先 执行项目打包命令

//项目打包代码 npm run build 
const compileDist = async () => {
  const loading = ora( defaultLog('项目开始打包') ).start();
  loading.spinner = spinner_style.arrow4;
  shell.cd(path.resolve(__dirname, '../'));
  const res = await shell.exec('npm run build'); //执行shell 打包命令
  loading.stop();
  if(res.code === 0) {
    successLog('项目打包成功!');
  } else {
    errorLog('项目打包失败, 请重试!');
    process.exit(); //退出流程
  }
}

然后 对打包的代码 /dist 目录打包 (如果不是dist, 请更改上面的 disDir 常量结尾的dist)

//压缩代码
const zipDist = async ()=>{
  defaultLog('项目开始压缩');
  try {
    await zipFile.zip.compressDir(distDir, distZipPath)
    successLog('压缩成功!');
  } catch (error) {
    errorLog(error);
    errorLog('压缩失败, 退出程序!');
    process.exit(); //退出流程
  }
}

再然后 通过ssh连接服务器 有两种方式: 一是通过秘钥连接(推荐), 二是密码连接 秘钥连接需要把本机公钥放服务器指定目录 (在upload/config.js 有说明) image.png

//连接服务器
const connectSSH = async ()=>{
  const loading = ora( defaultLog('正在连接服务器') ).start();
  loading.spinner = spinner_style.arrow4;
  try {
    await SSH.connect({
      host: config.SERVER_PATH,
      username: config.SSH_USER,
      // privateKey: config.PRIVATE_KEY, //秘钥登录(推荐) 方式一
      password: config.PASSWORD // 密码登录 方式二
    });
    successLog('SSH连接成功!'); 
  } catch (error) {
    errorLog(error);
    errorLog('SSH连接失败!');
    process.exit(); //退出流程
  }
  loading.stop();
}

紧接着 通过ssh执行线上命令 进行目标目录清空, 然后上传zip到服务器 并解压 等操作

//线上执行命令
/**
 * 
 * @param {String} command 命令操作 如 ls
 */
const runCommand = async (command)=> {
  const result = await SSH.exec(command, [], { cwd: config.PATH})
  // defaultLog(result);
}

//清空线上目标目录里的旧文件
const clearOldFile = async () =>{
  const commands = ['ls', 'rm -rf *'];
  await Promise.all(commands.map(async (it)=>{
    return await runCommand(it);
  }));
}

//传送zip文件到服务器
const uploadZipBySSH = async () =>{
  //连接ssh
  await connectSSH();
  //线上目标文件清空
  await clearOldFile();
  const loading = ora( defaultLog('准备上传文件') ).start();
  loading.spinner = spinner_style.arrow4;
  try {
    await SSH.putFiles([{ local: distZipPath, remote: config.PATH + '/dist.zip' }]); //local 本地 ; remote 服务器 ;
    successLog('上传成功!'); 
    loading.text = '正在解压文件';
    await runCommand('unzip ./dist.zip'); //解压
    await runCommand(`rm -rf ${config.PATH}/dist.zip`); //解压完删除线上压缩包
    //将目标目录的dist里面文件移出到目标文件  
    //举个例子 假如我们部署在 /test/html 这个目录下 只有一个网站, 那么上传解压后的文件在 /test/html/dist 里
    //需要将 dist 目录下的文件 移出到 /test/html ;  多网站情况, 如 /test/html/h5  或者 /test/html/admin 都和上面同样道理
    await runCommand(`mv -f ${config.PATH}/dist/*  ${config.PATH}`); 
    await runCommand(`rm -rf ${config.PATH}/dist`); //移出后删除 dist 文件夹
    SSH.dispose(); //断开连接
  } catch (error) {
    errorLog(error);
    errorLog('上传失败!');
    process.exit(); //退出流程
  }
  loading.stop();
}

把这些整合在一个函数

//------------发布程序---------------
const runUploadTask = async () => {
  console.log(chalk.yellow(`--------->  欢迎使用 波哥牌 2020年自动部署工具  <---------`));
  //打包
  await compileDist();
  //压缩
  await zipDist();
  //连接服务器上传文件
  await uploadZipBySSH(); 
  successLog('大吉大利, 部署成功!'); 
  process.exit();
}

发布前的检查配置

// 开始前的配置检查
/**
 * 
 * @param {Object} conf 配置对象
 */
const checkConfig = (conf) =>{
  const checkArr = Object.entries(conf);
  checkArr.map(it=>{
    const key = it[0];
    if(key === 'PATH' && conf[key] === '/') { //上传zip前会清空目标目录内所有文件
      errorLog('PATH 不能是服务器根目录!'); 
      process.exit(); //退出流程
    }
    if(!conf[key]) {
      errorLog(`配置项 ${key} 不能为空`); 
      process.exit(); //退出流程
    }
  })
}

执行交互 选择发布环境 然后启动发布程序

// 执行交互后 启动发布程序
inquirer
  .prompt([{
    type: 'list',
    message: '请选择发布环境',
    name: 'env',
    choices: [{
      name: '测试环境',
      value: 'development'
    },{
      name: '正式环境',
      value: 'production'
    }]
  }])
  .then(answers => {
    config = CONFIG[answers.env];
    checkConfig(config); // 检查
    runUploadTask(); // 发布
  });

大功告成


结尾

咳咳, 放心, 不会有公众号啥广告, 也不会求打赏, 如果您觉得对您有一点点帮助 点个赞或者去GitHub点个star 那就非常感谢了

[转载]原文链接:https://segmentfault.com/a/1190000020994461

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-79159.html

文章标题:前端自动化部署服务器, 告别繁琐部署过程

相关文章
前端工程师应该具备的三种思维
如果你是一个天才等级的工程师(马上可以离开),可以独立完成一个很多事情,你可以是一个怪咖,因为我相信没有一个人不会不佩服你。但现实归现实,多数人都不是天才,而我们在职场上也不是单打独斗,我们需要团队合作,需要协调和配合,需要考虑除了代码以外...
2016-01-13
nodejs搭建本地服务器并访问文件的方法
安装node:https://nodejs.org/en/download/ 在本地建立目录:f:/nodetest,在该目录下新建index.html作为我们将要访问的内容。新建server.js作为node开启的入口: $ cd f:&...
2017-03-13
前端开发领域推荐关注的微信公众号
这篇文章分享了前端领域的多个值得关注的技术、设计、极客、创业相关微信公众号。其中有最受欢迎的热门公众号、也有专注某个技术或设计的公众号,涵盖:算法、JavaScript、Nodejs、程序员、Web前端、Linux、数据库、创业、UI设计和...
2017-03-23
前端单页应用微服务化解决方案2 - Single-SPA
技术选型 经过各种技术调研我们最终选择的方案是基于 Single-SPA 来实现我们的前端微服务化. Single-SPA 一个用于前端微服务化的JavaScript前端解决方案 使用Single-SPA之后,你可以这样做: (兼容各...
2018-09-07
五个值得尝试的前端开发工具
在过去的几年时间里,出现了许多全新的网页应用程序,不过,由于应用程序的功能越来越丰富,也导致了前端开发的复杂度大幅增加。 现在也有不少前端开发工具,比如Backbone和EmberJS框架都能提供稳定的App开发解决方案。同时,Javasc...
2015-12-23
如何用js 实现依赖注入的思想,后端框架思想搬到前端来
大家在做些页面的时候,很多都是用ajax实现的,在显示的时候有很多表单提交的add或者update操作,显然这样很烦,突然想到了一个比较好的方法,下面给大家分享下如何用js 实现依赖注入的思想,后端框架思想搬到前端来。 应用场景: 前后端一...
2017-03-29
Vue.js bootstrap前端实现分页和排序
写之前先抱怨几句。本来一心一意做.net开发的,渐渐地成了只做前端。最近项目基本都用java做后台,我们这些.net的就成了前端,不是用wpf做界面,就是用html写web页面。 深知自己前端技术不足,以前虽说用asp.net前后台都做,但...
2017-03-14
前端E2E测试框架 cypress了解一下
What is E2E? 所谓的E2E就是end-to-end。 假设我们编写的每个功能程序都是一个黑匣子,最终用户也只会看到这个黑匣子,那么站在用户的角度来看并不需要知道这个黑匣子内部是什么东西也不需要知道怎么实现的,我只管知道最终效果是...
2018-04-29
nuxt.js部署vue应用到服务端过程
由于seo的需要,最近将项目移植道nuxt.js下采用ssr渲染 移植完成后,一路顺畅,但是到了要部署到服务器端上时候,还是个头疼的问题,但最终还是顺利完成。 现在记录一下部署中的过程。 注:部署时候过程中,参考了下:https://seg...
2018-04-18
JavaScript 常见安全漏洞和自动化检测技术
前言 随着 Web2.0 的发展以及 Ajax 框架的普及,富客户端 Web 应用(Rich Internet Applications,RIA)日益增多,越来越多的逻辑已经开始从服务器端转移至客户端,这些逻辑通常都是使用 JavaScri...
2017-03-29
回到顶部