天天看點

前端指令上傳伺服器

  1. 第一種方式: gulp 打包後的檔案上傳至伺服器

    下載下傳:

    npm install -D gulp-sftp-up4 gulp-ssh

    package.json:

    "scripts": { "server-dev": "cross-env NODE_ENV=dev gulp default },

    const { task, src, series } = require('gulp');
    const sftp = require('gulp-sftp-up4');
    const devConfig = {
    	  	host: '119.23.**.***',
    	  	port: 888,
    	  	user: 'root',
    		pass: '****',
    		remotePath: '/usr/local/nginx/html/test'
    }
    const testConfig = {
       	    host: '47.106.***.***',
    		port: 888,
    		user: 'root',
    		pass: '****',
    		remotePath: '/usr/local/nginx/html/webapps/test'
    }
    const gulpConfig = process.env.NODE_ENV === 'dev' ? devConfig : testConfig
    task('upload', function (done) {
      return src('./build/**')
        .pipe(sftp(gulpConfig));
    })
    task('default', series('upload'));
               
  2. 第二種方式: node 打包

    打包、壓縮、删除源代碼、上傳 一條龍。

    效果:

    前端指令上傳伺服器

1、commander : 在執行的時候增加參數,判斷環境

const { program } = require('commander');
program
  .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue'); // 預設值 blue
program.parse(process.argv);
console.log(`cheese: ${program.cheese}`);
           

終端執行node:

--cheese

得到結果: cheese: blue

--cheese green

得到結果: cheese: green

2、ora:處理終端轉輪狀态

成功、失敗、運作中等狀态

ora 優雅的終端轉輪

const ora = require('ora')
  ora().fail('請配置部署環境')
           

如圖顯示:

前端指令上傳伺服器

3、inquirer:使用者與指令行互動

詢問是否進行環境的部署:

const inquirer = require('inquirer')
    const answer = await inquirer.prompt([{
      type: 'confirm',
      message: '是否進行部署?',
      name: 'confirm', // 互動的關鍵字,如果有多條資料可以在這邊擷取到
    }])
    console.log("answer", answer.confirm)
           
const chalk = require('chalk')
const ora = require('ora')

// 成功資訊
const succeed = (message) => {
  ora().succeed(chalk.greenBright.bold(message))
}

// 提示資訊
const info = (message) => {
  ora().info(chalk.blueBright.bold(message))
}

// 錯誤資訊
const error = (message) => {
  ora().fail(chalk.redBright.bold(message))
}

// 下劃線重點資訊
const underline = (message) => {
  return chalk.underline.blueBright.bold(message)
}
           
// 使用
   succeed("成功啦~~~")
   error("失敗了- -")
   info(`提示 。。。${underline("下劃線* *")}`)
           
// 執行打包
const childProcess = require('child_process');
const maxBuffer = 5120 * 1024
const ora = require('ora')

function execBuild() {
  const spinner = ora('正在打包中...\n')
  spinner.start()
  return new Promise((resolve, reject) => {
    childProcess.exec('yarn build', {
      cwd: process.cwd(),
      maxBuffer: maxBuffer,
    }, (error, stdout, stderr) => {
      spinner.stop()
      if (error) {
        error(`打包出錯: ${error}`)
        reject(error)
        return;
      }
      succeed('打包成功')
      resolve(stdout)
    })
  })
}
           
const { program } = require('commander')
const chalk = require('chalk')
const ora = require('ora')
const inquirer = require('inquirer')
const childProcess = require('child_process')
const fs = require('fs')
const archiver = require('archiver')
const { NodeSSH } = require('node-ssh')

const ssh = new NodeSSH()
const maxBuffer = 5120 * 1024
let taskList = [] // 任務隊列

const config = {
  dev: {
    host: '119.23.**.***',
    port: 888,
    username: 'root',
    password: '****',
    local: 'build',
    remote: '/usr/local/nginx/html/test', // 伺服器部署路徑(不可為空或'/')
    script: 'yarn build',
  },
  test: {
    host: '47.106.**.***',
    port: 888,
    username: 'root',
    password: '****',
    local: 'build',
    remote: '/usr/local/nginx/html/test', // 伺服器部署路徑(不可為空或'/')
    script: 'yarn build',
  }
}

// 成功資訊
const succeed = (message) => {
  ora().succeed(chalk.greenBright.bold(message))
}
// 提示資訊
const info = (message) => {
  ora().info(chalk.blueBright.bold(message))
}
// 錯誤資訊
const error = (message) => {
  ora().fail(chalk.redBright.bold(message))
}
// 下劃線重點資訊
const underline = (message) => {
  return chalk.underline.blueBright.bold(message)
}


// 執行打包
async function execBuild(sshConfig, index) {
  const spinner = ora('正在打包中...\n')
  spinner.start()
  const { script } = sshConfig
  return new Promise((resolve, reject) => {
    childProcess.exec(script, {
      cwd: process.cwd(),
      maxBuffer: maxBuffer,
    }, (error, stdout, stderr) => {
      spinner.stop()
      if (error) {
        error(`打包出錯: ${error}`)
        reject(error)
        return;
      }
      succeed(`${index}. 打包成功`)
      resolve(stdout)
    })
  })
}

// 壓縮檔案
async function buildZip(sshConfig, index) {
  const { local } = sshConfig
  return new Promise((resolve, reject) => {
    const output = fs.createWriteStream(`${process.cwd()}/${local}.zip`);
    const archive = archiver('zip', {
      zlib: { level: 9 } // Sets the compression level.
    });
    output.on('close', function (e) {
      if (e) {
        error(`壓縮失敗${e}`)
        reject(e)
      } else {
        succeed(`${index}. 壓縮成功`)
        resolve()
      }
    });
    archive.pipe(output);
    archive.directory(local, false)
    archive.finalize();
  })
}

// 連接配接伺服器
async function connectSSH(sshConfig, index) {
  try {
    await ssh.connect(sshConfig)
    succeed(`${index}. ssh連接配接成功`)
  } catch (e) {
    error('連接配接失敗')
    process.exit(1)
  }
}

// 上傳檔案
async function putFileRemote(sshConfig, index) {
  try {
    const { local, remote } = sshConfig
    const spinner = ora('正在上傳中...\n')
    spinner.start()
    await ssh.putFile(`${process.cwd()}/${local}.zip`, `${remote}.zip`, null, { concurrency: 1 })
    spinner.stop()
    succeed(`${index}. 檔案成功上傳ssh`)
  } catch (e) {
    console.log(e)
    error(`檔案上傳ssh失敗${e}`)
    process.exit(1)
  }
}

// 删除服務端檔案
async function removeRemoteFile(sshConfig, index) {
  try {
    const { local, remote } = sshConfig
    const spinner = ora('正在删除服務端檔案中...\n')
    spinner.start()
    await ssh.execCommand(`rm -rf ${remote}/static`)
    spinner.stop()
    succeed(`${index}. 删除服務端檔案成功`)
  } catch (e) {
    error(`删除服務端檔案失敗${e}`)
    process.exit(1)
  }
}

// 解壓服務端檔案
async function unzipRemoteFile(sshConfig, index) {
  try {
    const { local, remote } = sshConfig
    const zipFileName = `${remote}.zip`
    const spinner = ora('正在解壓服務端檔案中...\n')
    spinner.start()
    await ssh.execCommand(`unzip  -o ${zipFileName} -d ${remote} && rm -rf ${zipFileName}`)
    spinner.stop()
    succeed(`${index}. 解壓服務端檔案成功`)
  } catch (e) {
    error(`解壓服務端檔案失敗${e}`)
    process.exit(1)
  }
}

// 删除本地檔案
async function removeLocalFile(sshConfig, index) {
  try {
    const { local } = sshConfig
    const localFileName = `${local}.zip`
    await fs.unlinkSync(localFileName)
    succeed(`${index}. 删除本地檔案成功`)
  } catch (e) {
    error(`删除本地檔案失敗${e}`)
    process.exit(1)
  }
}

// 斷開連接配接
async function disconnectSSH(sshConfig, index) {
  try {
    await ssh.dispose()
    succeed(`${index}. 成功斷開連接配接`)
  } catch (e) {
    error(`斷開連接配接失敗${e}`)
    process.exit(1)
  }
}

// 任務執行隊列
function handleTaskList() {
  taskList.push(execBuild)
  taskList.push(buildZip)
  taskList.push(connectSSH)
  taskList.push(putFileRemote)
  taskList.push(removeRemoteFile)
  taskList.push(unzipRemoteFile)
  taskList.push(removeLocalFile)
  taskList.push(disconnectSSH)
}

// 執行任務隊列
async function executeTaskList(sshConfig) {
  for (let index = 0; index < taskList.length; index++) {
    const exectue = taskList[index];
    await exectue(sshConfig, index + 1)
  }
}

// 檢查環境配置
function checkEnvCorrect(sshConfig, mode) {
  const keys = [,
    'host',
    'port',
    'username',
    'password',
    'local',
    'remote',
    'script'
  ]
  keys.forEach((item) => {
    const key = sshConfig[item]
    if (!key || key === '/') {
      error(`配置錯誤: ${underline(`${mode}環境`)} ${underline(`${item}屬性`)} 配置不正确`)
      process.exit(1)
    }
  })
}


const main = async (mode) => {
  if (mode) {
    const answer = await inquirer.prompt([{
      type: 'confirm',
      message: '是否進行部署?',
      name: 'confirm', // 互動的關鍵字,如果有多條資料可以在這邊擷取到
    }])
    const currentTime = new Date().getTime()
    if (answer.confirm) {
      const sshConfig = config[mode]
      checkEnvCorrect(sshConfig, mode)
      handleTaskList()
      await executeTaskList(sshConfig)
      const nowTime = new Date().getTime()
      succeed(`????????????恭喜,項目部署成功,耗時${(nowTime - currentTime) / 1000}s \n`)
      process.exit(0)
    } else {
      info('取消部署')
    }
  } else {
    error('請配置部署環境 --mode')
    process.exit(1)
  }
}

program
  .option('-m, --mode <type>', 'add the specified type of dev', 'dev')
  .action((options) => {
    // console.log(options.mode);
    main(options.mode)
  });;

program.parse(process.argv);

           

繼續閱讀