自动打包备份脚本
自动打包备份脚本
浮川的小窝

自动打包备份脚本

面壁人浮川
2023-07-31 发布 / 正在检测是否收录...

877a9fb9f1c0902a3a46145c2b62064d.jpeg


最近看着公司项目打包太过混乱 表情 因为协同开发 需要随时更新代码到测试环境 虽然有git的自动化部署脚本 但是上了正式的内网环境(政府项目无互联网环境) 打包还是要手动部署的 所以想写个简单的备份脚本 发包的时候能知道最后发包人及发包时间和版本 表情 话不多说 上代码

项目结构:
项目结构.jpg

添加tsconfig.run.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2018",
    "strict": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "moduleResolution": "node"
  },
  "include": ["build/index.ts"]
}

添加build下index.ts

注意安装 npm install ts-node
archiver @types/archiver -D
import * as fs from "fs";
import path from "path";
import moment from "moment";
import { exec } from "child_process";
import archiver from "archiver";

// 文件数
let files = 0;
// 获取文件路径
const getPath = (dir: string) => path.resolve(__dirname, "../", dir),
  archive = archiver("zip", {
    zlib: { level: 6 },
  }),
  // 获取git用户名
  getGitUser = () => {
    return new Promise((resolve, reject) => {
      exec("git config user.name", (err, stdout) => {
        if (err) {
          console.log("未获取到当前打包人:", err);
          return reject("未知");
        }
        console.log("当前打包人:", stdout.slice(0, -1));
        resolve(stdout.slice(0, -1));
      });
    });
  },
  // 获取文件数
  dirLen = (srcPath: string) => {
    fs.readdirSync(srcPath).forEach((dir) => {
      const filePath = path.join(srcPath, dir);
      if (fs.lstatSync(filePath).isDirectory()) {
        dirLen(filePath);
      } else files += 1;
    });
  },
  // 遍历读取文件
  readDirErgodic = async (
    srcPath: string,
    toPath: string,
    callback: () => void
  ) => {
    try {
      const dirList = fs.readdirSync(srcPath);
      for await (const file of dirList) {
        //拼接路径
        const curPath = path.join(srcPath, file),
          toCopyPath = path.join(toPath, file);
        if (fs.lstatSync(curPath).isDirectory()) {
          fs.mkdirSync(toCopyPath);
          readDirErgodic(curPath, toCopyPath, callback);
        } else {
          const readable = fs.createReadStream(curPath),
            writable = fs.createWriteStream(toCopyPath);
          readable.pipe(writable);
          writable.on("finish", () => {
            files--;
            // files === 0 && console.log("finish", callback);
            files === 0 && callback && callback();
          });
        }
      }
    } catch (err) {
      console.log("------------读取dist文件失败------------", err);
      throw new Error(err + "");
    }
  },
  // 读取dist下所有文件
  readDistDir = async (srcPath: string, toPath: string) => {
    try {
      // 计算多少文件数
      dirLen(srcPath);
      // 创建复制过去准备打包的文件夹
      fs.mkdirSync(toPath);
      console.log("打包文件个数:", files);
      return new Promise((resolve) => {
        readDirErgodic(srcPath, toPath, () => resolve(true));
      });
    } catch (err) {
      return Promise.resolve(false);
    }
  },
  // 删除指定文件夹下所有文件并删除该文件夹
  deleteFolderErgodic = async (folderPath: string) => {
    const files = fs.readdirSync(folderPath);
    for await (const filePath of files) {
      //拼接路径
      const curPath = path.join(folderPath, filePath);
      if (fs.lstatSync(curPath).isDirectory()) {
        await deleteFolderErgodic(curPath);
        isEmptyDir(curPath) && fs.rmdirSync(curPath);
      } else {
        fs.unlinkSync(curPath);
      }
    }
    return Promise.resolve(true);
  },
  // 是否为空文件夹
  isEmptyDir = (folderPath: string) => {
    try {
      const list = fs.readdirSync(folderPath);
      return list && Array.isArray(list) && list.length === 0 ? true : false;
    } catch (e) {
      return true;
    }
  },
  // 删除指定文件夹
  deleteFolder = async (folderPath: string) => {
    await deleteFolderErgodic(folderPath);
    // 删除现在为空的文件夹
    // console.log("isEmptyDir(folderPath)", isEmptyDir(folderPath));
    isEmptyDir(folderPath) && fs.rmdirSync(folderPath);
  },
  // 打包文件
  compressFolder = async (fileName: string) => {
    if (fs.existsSync(fileName)) {
      console.log("------------打包压缩开始------------");
      const output = fs.createWriteStream(`${fileName}.zip`);
      // 监听archive对象的错误事件
      archive.on("error", (err: any) => {
        console.log("打包错误", err);
        throw err;
      });
      output.on("close", () => {
        let times = 3;
        console.log("------------删除打包文件中....------------");
        const timer: NodeJS.Timer = setInterval(() => {
          console.log(`${times}秒`);
          if (times == 1) {
            if (fs.existsSync(fileName)) {
              deleteFolder(fileName);
              console.log("------------打包压缩流程完成!------------");
              return clearInterval(timer);
            } else
              console.log(
                "------------删除打包文件失败,请根据情况手动删除------------"
              );
          }
          times--;
        }, 1000);
      });
      // 将archive流导向输出文件
      archive.pipe(output);
      // 添加要打包的文件
      archive.directory(fileName, false);
      // 完成archive
      archive.finalize();
    }
  };
// 将打包的dist文件存入文件备份中
(async function copyFileToBackFiles(srcFile: string, distFile: string) {
  console.log("------------打包压缩流程开始!------------");
  !fs.existsSync(distFile) && fs.mkdirSync(distFile);
  const fileName = `${distFile}/${path.basename(process.cwd())}-${moment(
    new Date()
  ).format("YYYY-MM-DD HH:mm:ss")}-${await getGitUser()}`;
  //
  // console.log("fileName", path.basename(process.cwd()));
  // 读取dist文件夹下所有文件并拷贝到fileName文件夹下
  if (!(await readDistDir(srcFile, fileName)))
    return console.log("------------打包压缩意外终止------------");
  // 压缩文件
  compressFolder(fileName);
})(getPath("dist"), getPath("dist_back_files"));

package.json添加运行脚本

{
  "build-only": "vite build && ts-node",
  "ts-node": "ts-node --project tsconfig.run.json build/index",
}

脚本将在构建完成后 创建一个
打包.jpg
压缩文件名组成: 项目名-日期-git最后一次提交人 表情

暂时性满足了我的需求 后期准备把他封装成一个插件包发上去 等着再说叭~

© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 收藏

评论 (0)

取消