前端项目中创建自动化部署脚本,用于 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"
}
相关推荐
_AaronWong1 小时前
Electron 实现仿豆包划词取词功能:从 AI 生成到落地踩坑记
前端·javascript·vue.js
cxxcode1 小时前
I/O 多路复用:从浏览器到 Linux 内核
前端
用户5433081441941 小时前
AI 时代,前端逆向的门槛已经低到离谱 — 以 Upwork 为例
前端
JarvanMo1 小时前
Flutter 版本的 material_ui 已经上架 pub.dev 啦!快来抢先体验吧。
前端
恋猫de小郭2 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
哀木2 小时前
给自己整一个 claude code,解锁编程新姿势
前端
程序员鱼皮2 小时前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
UrbanJazzerati2 小时前
Vue3 父子组件通信完全指南
前端·面试
是一碗螺丝粉2 小时前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain
wuhen_n2 小时前
双端 Diff 算法详解
前端·javascript·vue.js