node-ssh搭建前端自动构建集成工具

320 阅读6分钟

前言

如果现在的你没有使用前端自动构建集成工具,又苦于每次打包后使用SFTP工具上传太麻烦,下边这个简单的自动化集成工具或许你会感兴趣。

分析

使用的SFTP工具的流程: 使用node-ssh替代SFTP工具流程: 具体实现流程:

设计

接下来我们就打造打包发布工具,我给他取名publish-tools。为了安全起见和通用性,把配置文件(publish.config.js)放在项目里,做成npm包命令行工具。

工具

编写配置文件

以配置两个测试环境为例(dev,dev2)

  1. 可以选择打包发布2个测试环境;
  2. 可以查看打包日志;

可以设计成这样:

 module.exports = {
    option: {
        dev: {
        remoteDir: ''//服务器地址
        host: '', 
        username: '',
        passdword: '',
        script: ``, // 执行打包命令  npm run build
        localDir: '' // 本地上传的文件夹   ./dist/dev
        },
        dev2: {
        remoteDir: '',
        host: '',
        username: '',
        passdword: '',
        script: '',
        localDir: ''
        }
    },
    logs: false   // 日志
    }

编写npm 包

初始化配置

  1. 执行npm init

  2. 命名: publish-tools

  3. 在package.json 中加上

 "bin": { //命令名:文件名
    "publishTest": "./index.js"
  },
  1. 下载依赖
yarn add chalk commander inquirer node-ssh ora glob

开发

1.建立index.js 文件

2.在文件顶部加上#!/usr/bin/env node

#!/usr/bin/env node
const path = require("path");
const program = require("commander");
const child_process = require("child_process");
const util = require("util");
const chalk = require('chalk');
const inquirer = require("inquirer");
const process = require("process");
const pka = require("./package.json");
const ora = require("ora");
const glob = require("glob");
const { NodeSSH } = require("node-ssh");
const ssh = new NodeSSH();
const exec = util.promisify(child_process.exec); // 使用子进程执行shell命令
const arr = glob.sync(`${process.cwd()}/publish.config.js`); // 加载工作目录的配置文件

注:文件换行符改为:LF,防止出现不必要的报错

3.判断配置文件

 function log(str, color = 'white') {
        console.log(chalk[color](str))
    }
  function checkConf(cos) {
  const target = ["remoteDir""host""username""passdword""script""localDir"];
    if(!cos) {
        log(`中缺少参数option`, "red");
        return false
      }
      let flag = true
    for (let item in cos) {
      const arr = Object.keys(cos[item]);
      target.forEach((e) => {
        if (arr.indexOf(e) == -1) {
          log(`${item}中缺少参数${e}`, "red");
          flagfalse;
        }
      });
    }
    // console.log(cos)
    return flag;
  }
let config = null; // 配置文件
let types = []; //交互命令选择
let pointLog = false; // 是否打印日志
if (arr.length) {
  const src = arr[0];
  const { option, logs } = require(src);
  if (option) config = option;
  if (logs) pointLog = logs;
  if (!checkConf(config)) {
    return;
  } else {
    types = Object.keys(config);
  }
} else {
  log(`${process.cwd()}中没有publish.config.js`, "red");
  return;
}
if (!config || !types.length) return;

4.测试命令行命令 在package.json加上

"scripts": {
    "test": "node ./index.js publish" // 相当于`publishTest publish`
  }

index.js加入命令行

program
  .version(pka.version, "-v, --version"// publishTest -v 版本号
  .option("publish, publish""本地打包发布工具"// publishTest publis =>执行publish 命令
  .command("publish")
  .action( () => { //publish 命令所执行的代码
  // 选择要发布的环境
  });
  
  program.parse(process.argv);
  1. 选择要发布的环境
 const { devType } = await inquirer.prompt([
      {
        name"devType",
        type"list",
        message`请选择发布的测试版本.`,
        choices: types.filter((e) => {  //dev,dev2
          return {
            name: e,
            value: e,
          };
        }),
        default: types[0],
      },
    ]);
    const selectConfig = config[devType]; // 选择的配置
    const spinner = ora("开始打包...");  // 动画
    spinner.start();
    pointLog && log(`配置: ${JSON.stringify(selectConfig, null2)}`);
    pointLog && log(`执行命令:${selectConfig.script}`);
    // 执行本地打包命令
  1. 执行本地打包命令
 exec(selectConfig.script, { encoding: "utf8" }) // 执行配置文件中的script
      .then((stdoutstderr) => {
        if (pointLog) { // 打包日志
          console.log(stdout);
          console.log(stderr);
        }
        spinner.succeed(); 
        // ssh连接服务器
        })
  1. 连接服务器
//selectConfig  => 选择的配置文件
 ssh.connect({
            host: selectConfig.host,
            username: selectConfig.username,
            port: selectConfig.port || 22,
            password: selectConfig.passdword,
            tryKeyboardtrue,
          })
          .thenfunction () {
            log(`连接服务器成功`"green");
            log(`开始上传文件`"green");
          // 上传文件
          })
  1. 上传文件
//distDir:本地上传 目录,remoteDir:远程目录
ssh.putDirectory(distDir, selectConfig.remoteDir, { 
                  // 文件上传回调
                tickfunction (localPath, remotePath, error) {
                  if (error) {
                    log(error, "red");
                  } else {
                    pointLog &&
                      log(`传输:${localPath}  -> ${remotePath}`"green");
                  }
                },
              })
              .then(function () {
              // 上传成功
              })

到这里npm包已经制作完成。接下来可以发布到npm上了

npm login

npm who am i

npm publish

本地发布成功

结语

以上就是publish-tools工具的制作流程,已发布到npm上,有需要的可以下载使用。欢迎各位看官提出宝贵的意见。