前端项目中创建自动化部署脚本,用于 Jenkins 触发 npm run publish 来完成远程部署

核心步骤包括:

  1. 读取 server.config.json 配置,获取目标服务器信息
  2. 使用 scp 上传前端打包文件serverWebPath
  3. 使用 ssh 远程执行部署命令 (例如 pm2 restartnginx reload

1. 安装依赖

使用 Node.js 编写 deploy.js 脚本,需要用到 ssh2fs

npm install ssh2 fs-extra dotenv

2. 在config下配置server.config.json文件

javascript 复制代码
{
  "deploy": {
    "host": "10.2...",
    "port": 36000,
    "username": "root",
    "password": "*#00000",
    "serverWebPath": "/...",
    "splitIncludes": ["models"],
    "splitUpload": false
  },
  "sandbox": {
    "host": "10.2...",
    "port": 36000,
    "username": "root",
    "password": "*#00000",
    "serverWebPath": "/...",
    "splitIncludes": [],
    "splitUpload": true
  }
}

3. deploy.js 自动化脚本

项目根目录 创建 scripts/deploy.js,用于 自动化部署

javascript 复制代码
const fs = require("fs-extra");
const path = require("path");
const { Client } = require("ssh2");

// 读取 server.config.json
const configPath = path.resolve(__dirname, "../server.config.json");
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));

// 选择环境(deploy 或 sandbox)
const env = process.env.ENV || "deploy";
const serverConfig = config[env];

if (!serverConfig) {
  console.error(`配置错误: 未找到环境 ${env} 的配置信息`);
  process.exit(1);
}

// 获取配置信息
const { host, port, username, password, serverWebPath } = serverConfig;
const localBuildPath = path.resolve(__dirname, "../dist"); // 前端打包目录

// 部署逻辑
async function deploy() {
  console.log(`开始部署到 ${env} 环境: ${host}:${port}`);

  const conn = new Client();
  conn
    .on("ready", () => {
      console.log(`连接成功: ${host}`);

      // 上传文件
      uploadFiles(conn)
        .then(() => executeRemoteCommand(conn, `cd ${serverWebPath} && ls -la`))
        .then(() => {
          console.log("部署完成!");
          conn.end();
        })
        .catch((err) => {
          console.error(`部署失败: ${err.message}`);
          conn.end();
        });
    })
    .connect({ host, port, username, password });
}

// 远程执行命令
function executeRemoteCommand(conn, command) {
  return new Promise((resolve, reject) => {
    conn.exec(command, (err, stream) => {
      if (err) return reject(err);
      stream
        .on("close", (code, signal) => resolve(code))
        .on("data", (data) => console.log(`远程输出: ${data.toString()}`))
        .stderr.on("data", (data) => console.error(` 错误: ${data.toString()}`));
    });
  });
}

// 上传文件
function uploadFiles(conn) {
  return new Promise((resolve, reject) => {
    conn.sftp((err, sftp) => {
      if (err) return reject(err);
      sftp.mkdir(serverWebPath, (err) => {
        if (err && err.code !== 4) return reject(err); // 目录已存在则忽略错误
        sftp.fastPut(
          path.join(localBuildPath, "index.html"),
          `${serverWebPath}/index.html`,
          (err) => (err ? reject(err) : resolve())
        );
      });
    });
  });
}

// 执行部署
deploy();

4. 在 package.json 添加 publish 命令

javascript 复制代码
"scripts": {
  "build": "vite build",
  "publish": "npm run build && node scripts/deploy.js"
}
相关推荐
青年优品前端团队5 小时前
🚀 不仅是工具库,更是国内前端开发的“瑞士军刀” —— @qnvip/core
前端
北极糊的狐5 小时前
Vue3 中父子组件传参是组件通信的核心场景,需遵循「父传子靠 Props,子传父靠自定义事件」的原则,以下是资料总结
前端·javascript·vue.js
看到我请叫我铁锤6 小时前
vue3中THINGJS初始化步骤
前端·javascript·vue.js·3d
q***25216 小时前
SpringMVC 请求参数接收
前端·javascript·算法
q***33376 小时前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
烛阴6 小时前
从`new()`到`.DoSomething()`:一篇讲透C#方法与构造函数的终极指南
前端·c#
还债大湿兄6 小时前
阿里通义千问调用图像大模型生成轮动漫风格 python调用
开发语言·前端·python
谢尔登7 小时前
defineProperty如何弥补数组响应式不足的缺陷
前端·javascript·vue.js
蓝瑟忧伤7 小时前
前端技术新十年:从工程体系到智能化开发的全景演进
前端
Baklib梅梅7 小时前
员工手册:保障运营一致性与提升组织效率的核心载体
前端·ruby on rails·前端框架·ruby