前端项目构建打包生成Git信息文件

news2024/11/16 3:23:23

请添加图片描述

系列文章目录

TypeScript 从入门到进阶专栏


文章目录

  • 系列文章目录
  • 前言
  • 一、前端项目构建打包生成Git信息文件作用
  • 二、步骤
    • 1.引入相关的npm包
      • 1.1. **fs** 包
      • 1.2. **child_process** 包
      • 1.3. **os** 包 (非必须 如果你想生成的文件信息中包含当前电脑信息则可用)
      • 1.4. **path** 包 (非必须 如果你想生成的文件信息中包含当前项目版本信息则可用)
    • 2.创建脚本文件
    • 2.设置项目打包脚本
    • 3.运行项目打包命令
  • 我的脚本文件


前言

前端项目构建打包生成Git信息文件的作用是将当前代码所属的Git仓库的相关信息(例如commit hash、branch name、commit message等)保存在项目中的一个文件中。这样做的目的是为了方便在程序中获取和展示当前代码的版本信息,以及方便对项目进行版本管理和追踪。

一、前端项目构建打包生成Git信息文件作用

  1. 便于查看当前代码所属的Git分支和最近的commit hash,方便开发人员进行调试和追踪问题。
  2. 方便在应用程序界面或其他需要展示版本信息的地方展示当前代码的版本号,以便用户了解当前使用的是哪个版本的代码。
  3. 在持续集成和部署流程中,可以将生成的Git信息文件上传到服务器,方便在服务器端查看和追踪部署到服务器的代码版本。
  4. 可以结合自动化工具或脚本,在每次构建打包过程中自动更新Git信息文件,以保证该文件中的版本信息与当前代码一致,方便后续的版本管理和追踪。
  5. 方便开发人员在使用第三方工具或库时,能够快速确定所使用的版本,以解决可能出现的兼容性或功能问题。

二、步骤

1.引入相关的npm包

首先我们需要在项目中安装四个需要的npm包

1.1. fs

作用:提供了文件系统相关的功能,允许你在Node.js环境中对文件进行读取、写入、修改、删除等操作。。 用于生成最后的信息文件

安装方式如下

npm install fs --save-dev
或
pnpm add --save-dev
或
yran install fs --save-dev

1.2. child_process

是一个用于创建子进程的模块。它提供了一些方法来执行外部命令、创建子进程,并与其进行通信。

安装方式如下

npm install child_process --save-dev
或
pnpm child_process --save-dev
或
yran install child_process --save-dev

1.3. os 包 (非必须 如果你想生成的文件信息中包含当前电脑信息则可用)

os包可以让开发者在Node.js环境中访问操作系统相关的功能。

安装方式如下

npm install os --save-dev
或
pnpm os --save-dev
或
yran install os --save-dev

os包的方法

  1. os.platform():获取当前操作系统的平台名称,例如’win32’、'linux’等。
  2. os.arch():获取当前操作系统的CPU架构,例如’x64’、'arm’等。
  3. os.hostname():获取当前计算机的主机名。
  4. os.type():获取当前操作系统的类型,例如’Windows_NT’、'Linux’等。
  5. os.release():获取当前操作系统的版本号。
  6. os.totalmem():获取当前系统的总内存大小。
  7. os.freemem():获取当前系统的可用内存大小。
  8. os.cpus():获取当前计算机的CPU信息。
  9. os.networkInterfaces():获取当前计算机的网络接口信息。

1.4. path 包 (非必须 如果你想生成的文件信息中包含当前项目版本信息则可用)

npm install path --save-dev
或
pnpm path --save-dev
或
yran install path --save-dev

2.创建脚本文件

在项目的根目录文件下创建 automated_scripts 文件夹 在此文件夹下创建 build.js 文件 如下图所示。也可以放在别的位置 根据自己的项目来 。

请添加图片描述

build.js 文件 整体代码如下:

import fs from 'fs'; // 引入文件系统
import { execSync } from 'child_process'; // 开启一个子进程
import path from 'path';
import os from 'os';

// 获取当前命令行上下文路径
const currentDirectory = process.cwd();

// 日期格式转换函数  格式: 2024-1-10 16:57:40
const transferTime = (date) => {
	const currentDate = date ? new Date(date) : new Date();
	const year = currentDate.getFullYear();
	const month = currentDate.getMonth() + 1; // getMonth() 返回的是 0-11,需要加 1
	const dates = currentDate.getDate();
	const hours = currentDate.getHours();
	const minutes = currentDate.getMinutes();
	const seconds = currentDate.getSeconds();
	return `${hours}:${minutes}:${seconds} ${year}-${month}-${dates}`;
};

//主体函数
async function start() {
	console.log('\x1B[32m', '开始打包项目', '\x1B[0m');
	
	// 执行npm打包命令 这里根据 你自己项目打包时运行的命令进行修改 一般是vite build 
		execSync('vite build --mode production', {
			stdio: 'inherit',
		});
	// 获取当前git分支名称
		const branchName = execSync('git rev-parse --abbrev-ref HEAD')
			.toString()
			.trim();	
		//打包时间
		const date = new Date().toLocaleString();

		// 打印
		console.log(
			'\x1B[33m',
			'------------------------------------------',
			'\x1B[0m'
		);
		console.log(
			'\x1B[32m',
			'\t项目信息:\n' +
				`\t版本号:${currentVersion}\n` +
				`\t打包时间:${date}\n` +
				`\tgit分支名称:${branchName}\n`,
			'\x1B[0m'
		);
		console.log(
			'\x1B[33m',
			'------------------------------------------',
			'\x1B[0m'
		);
		
		const branch = execSync('git rev-parse --abbrev-ref HEAD')
			.toString()
			.trim();
		
		//此处添加git命令
		const gitDataMap ={
			'git.branch': 'git rev-parse --abbrev-ref HEAD',
			'git.commit.id': `git rev-parse --verify ${
				branch ? 'origin/' + branch : 'HEAD'
			}`,
			'git.commit.id.abbrev': `git rev-parse --short ${
				branch ? 'origin/' + branch : 'HEAD'
			}`,
			'git.commit.message.full': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%B"`,
			'git.commit.message.short': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%s"`,
			'git.commit.time': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%cd"`,
			'git.commit.user.email': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%ae"`,
			'git.commit.user.name': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%an"`,
			'git.dirty': 'git status --porcelain',
			'git.remote.origin.url': 'git remote get-url origin',
			'git.total.commit.count': 'git rev-list --count HEAD',
		}

		Object.keys(gitDataMap).forEach((value) => {
			newStr[value] = execSync(gitDataMap[value]).toString().trim();
		});

		//将日志写入dist文件夹下的 web.json
		fs.writeFile('dist/web.json', JSON.stringify(newStr), 'utf-8', (err) => {
			if (err != null) {
				console.log('ERROR:', err);
			} else {
				console.log('打包完成');
			}
		});


}

2.设置项目打包脚本

我这里是用vue项目为例子 React、Angular 项目也是差不多的做法

打开项目根目录下的 package.json文件 将scripts下的build 改成

node  automated_scripts/build.js

如下图
请添加图片描述

3.运行项目打包命令

pnpm run build

最终就能在项目打包的dist文件夹下生成一个 web.json文件

我的脚本文件

我这里实现了 获取项目信息 获取当前打包的电脑信息 获取get信息 及打包之前进行校验等功能

import fs from 'fs'; // 引入文件系统
import { execSync } from 'child_process'; // 开启一个子进程
import path from 'path';
import os from 'os';
//import packages from './package.json'
// 获取当前命令行上下文路径
const currentDirectory = process.cwd();

const transferTime = (date) => {
	const currentDate = date ? new Date(date) : new Date();
	const year = currentDate.getFullYear();
	const month = currentDate.getMonth() + 1; // getMonth() 返回的是 0-11,需要加 1
	const dates = currentDate.getDate();
	const hours = currentDate.getHours();
	const minutes = currentDate.getMinutes();
	const seconds = currentDate.getSeconds();
	return `${hours}:${minutes}:${seconds} ${year}-${month}-${dates}`;
};

/**
 * 检查本地是否有未提交的更改
 */
const checkChanges = async () => {
	try {
		//本地分支名称
		const branch = execSync('git rev-parse --abbrev-ref HEAD')
			.toString()
			.trim();
		//本地分支 commit hash
		const hash = execSync('git rev-parse HEAD').toString().trim();
		//远程分支 commit hash
		const remoteHash = execSync(
			`git rev-parse ${branch ? 'origin/' + branch : 'HEAD'}`
		)
			.toString()
			.trim();

		const data = execSync('git status').toString().trim();

		if (
			(data.includes('Changes to be committed') ||
				data.includes('Untracked files') ||
				data.includes('Changes not staged for commit') ||
				data.includes('use "git push" to publish your local commits')) &&
			hash !== remoteHash
		) {
			if (data.includes('Changes not staged for commit')) {
				console.log(
					'\x1B[33m',
					'本地项目有数据有文件未add或未commit,请先保存、提交远程 再进行打包',
					'\x1B[0m'
				);
			}
			if (data.includes('Untracked files')) {
				console.log(
					'\x1B[33m',
					'本地项目有数据有文件add了 但未进行commit,请先保存、提交远程 再进行打包',
					'\x1B[0m'
				);
			}
			if (data.includes('Changes to be committed')) {
				console.log(
					'\x1B[33m',
					'本地项目有数据有文件未add或未commit,请先保存、提交远程 再进行打包',
					'\x1B[0m'
				);
			}
			if (data.includes('use "git push" to publish your local commits')) {
				console.log(
					'\x1B[33m',
					'本地项目有数据有文件未push,请先提交远程 再进行打包',
					'\x1B[0m'
				);
			}
			if (hash !== remoteHash) {
				console.log(
					'\x1B[33m',
					'本地项目与远程分支不一致,请先同步再进行打包',
					'\x1B[0m'
				);
			}
			return 0;
		}
		return 1;
	} catch (error) {
		return 1;
	}
};

async function start() {
	console.log('\x1B[32m', '开始打包项目', '\x1B[0m');

	//版本号获取
	const packageJsonPath = path.join(currentDirectory, 'package.json');
	const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
	const packageJson = JSON.parse(packageJsonContent);
	const currentVersion = packageJson.version;
	console.log('\x1B[32m', `版本号:${currentVersion}\n`, '\x1B[0m');

	if (await checkChanges()) {
		// 执行npm打包命令
		execSync('vite build --mode production', {
			stdio: 'inherit',
		});

		// 获取当前git分支名称
		const branchName = execSync('git rev-parse --abbrev-ref HEAD')
			.toString()
			.trim();

		//打包时间
		const date = new Date().toLocaleString();

		// 打印
		console.log(
			'\x1B[33m',
			'------------------------------------------',
			'\x1B[0m'
		);
		console.log(
			'\x1B[32m',
			'\t项目信息:\n' +
				`\t版本号:${currentVersion}\n` +
				`\t打包时间:${date}\n` +
				`\tgit分支名称:${branchName}\n`,
			'\x1B[0m'
		);
		console.log(
			'\x1B[33m',
			'------------------------------------------',
			'\x1B[0m'
		);
		const newStr = {
			'git.build.host': '',
			'git.build.architecture': '',
			'git.build.os': '',
			'git.build.release': '',
			'git.build.time': '',
			'git.build.user.email': '',
			'git.build.user.name': '',
			'git.build.version': '',
		};

		//此处添加打包信息
		newStr['git.build.version'] = currentVersion;
		newStr['git.build.host'] = os.hostname();
		newStr['git.build.architecture'] = os.arch();
		newStr['git.build.os'] = os.type();
		newStr['git.build.release'] = os.release();
		newStr['git.build.time'] = transferTime();

		const branch = execSync('git rev-parse --abbrev-ref HEAD')
			.toString()
			.trim();

		//此处添加git命令
		const gitDataMap = {
			'git.branch': 'git rev-parse --abbrev-ref HEAD',
			'git.commit.id': `git rev-parse --verify ${
				branch ? 'origin/' + branch : 'HEAD'
			}`,
			'git.commit.id.abbrev': `git rev-parse --short ${
				branch ? 'origin/' + branch : 'HEAD'
			}`,
			'git.commit.message.full': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%B"`,
			'git.commit.message.short': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%s"`,
			'git.commit.time': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%cd"`,
			'git.commit.user.email': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%ae"`,
			'git.commit.user.name': `git log -1 ${
				branch ? 'origin/' + branch : ''
			} --format="%an"`,
			'git.dirty': 'git status --porcelain',
			'git.remote.origin.url': 'git remote get-url origin',
			'git.total.commit.count': 'git rev-list --count HEAD',
		};

		Object.keys(gitDataMap).forEach((value) => {
			newStr[value] = execSync(gitDataMap[value]).toString().trim();
			if (value === 'git.commit.time') {
				newStr[value] = transferTime(newStr[value]);
			}
		});

		newStr['git.build.user.email'] = newStr['git.commit.user.email'];
		newStr['git.build.user.name'] = newStr['git.commit.user.name'];
		//将日志写入log.txt
		fs.writeFile('dist/web.version', JSON.stringify(newStr), 'utf-8', (err) => {
			if (err != null) {
				console.log('ERROR:', err);
			} else {
				console.log('打包完成');
			}
		});
	}
	// } else {
	//   console.log(
	//     '\x1B[31m',
	//     '本地有未提交的更改,请先提交 再进行打包',
	//     '\x1B[0m',
	//   )
	// }
}

start();


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1372544.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt QCheckBox复选按钮控件

文章目录 1 属性和方法1.1 文本1.2 三态1.3 自动排他1.4 信号和槽 2 实例2.1 布局2.2 代码实现 Qt中的复选按钮类是QCheckBox它和单选按钮很相似,单选按钮常用在“多选一”的场景,而复选按钮常用在"多选多"的场景比如喜欢的水果选项中&#xf…

Python从入门到网络爬虫(控制语句详解)

前言 做任何事情都要遵循一定的原则。例如,到图书馆去借书,就需要有借书证,并且借书证不能过期,这两个条件缺一不可。程序设计亦是如此,需要使用流程控制实现与用户的交流,并根据用户需求决定程序“做什么…

特征工程:图像数据不足时的处理办法

在机器学习中,绝大部分模型都需要大量的数据进行训练和学习(包括有监督学习和无监督学习),然而在实际应用中经常会遇到训练数据不足的问题。比如图像分类,作为计算机视觉最基本的任务之一,其目标是将每幅图…

Android学习(四):常用布局

Android学习(四):常用布局 五种常用布局 线性布局:以水平或垂直方向排列相对布局:通过相对定位排列帧布局:开辟空白区域,帧里的控件(层)叠加表格布局:表格形式排列绝对布局&#x…

Linux的基本指令(5)

目录 bc指令 uname指令 压缩解压相关的指令 zip指令 unzip指令 tar打包压缩指令 tar解压解包指令 ​传输指令sz&rz 热键 关机命令 安装:yum install -y 指令 bc指令 bc命令可以很方便的进行浮点运算 Linux中的计算器 uname指令 语法:unam…

MySQL之导入以及导出远程备份v

目录 一.navact数据导入导出 1.1 导入 1.2 导出 二. mysqldump命令导入导出数据 2.1 导入 2.2 导出 三.load data file进行数据导入导出(只限于单表) 3.1 导入 3.2 导出 四.远程连接 好啦就到这里了哦!!!希望帮到你哦!!! 一.navact数据导入导…

RIP复习实验

条件: R1为外网,R8和r9的环回分别是172.16.1.0/24和172.16.2.0/24 中间使用78.1.1.0/24 剩下的路由器2-6使用172.16.0.0/16 要求: R1为运营商 r1远程登录r2实际登录r7 R2访问r7要求走r5去访问 全网可达 实现流程: 首先配置好各接口ip address 然后r2-r7使用rip…

Python Matplotlib 库使用基本指南

简介 Matplotlib 是一个广泛使用的 Python 数据可视化库,它可以创建各种类型的图表、图形和可视化效果。无论是简单的折线图还是复杂的热力图,Matplotlib 提供了丰富的功能来满足我们的数据可视化需求。本指南将详细介绍如何安装、基本绘图函数以及常见…

Vue 自定义仿word表单录入之日期输入组件

因项目需要&#xff0c;要实现仿word方式录入数据&#xff0c;要实现鼠标经过时才显示编辑组件&#xff0c;预览及离开后则显示具体的文字。 鼠标经过时显示 正常显示及离开时显示 组件代码 <template ><div class"paper-input flex flex-col border-box "…

2024-01-03 无重叠区间

435. 无重叠区间 思路&#xff1a;和最少数量引爆气球的箭的思路基本都是一致了&#xff01;贪心就是比较左边的值是否大于下一个右边的值 class Solution:def eraseOverlapIntervals(self, points: List[List[int]]) -> int:points.sort(keylambda x: (x[0], x[1]))# 比较…

怎么把epub转换成word文档?

怎么把epub转换成word文档&#xff1f;在看电子书的时候&#xff0c;相信大家都接触过各种电子书格式&#xff0c;比如epub格式&#xff0c;这种格式优点很多&#xff0c;但有个致命的缺点就是编辑能力比较差&#xff0c;这种坏处带来的后果是非常严重的&#xff0c;会让我们无…

OCP NVME SSD规范解读-6.标准日志要求-2

STD-LOG-12:针对日志存储的类型定义了多种&#xff0c;复位&#xff08;包括控制器复位&#xff0c;NSSR、FLR、PCIe hot reset&#xff09;与断电重启POWER CYCLE有不同的操作要求。 STD-LOG-14: Lockdown命令是NVMe管理命令集中的一个命令&#xff0c;主要用于安全和管理目的…

数组和函数实践:扫雷游戏玩法和棋盘初始化(1)

各位少年&#xff0c;大家好&#xff0c;我是博主那一脸阳光&#xff0c;我们学会了数组&#xff0c;exturn声明外部文件&#xff0c;static修饰静态变量&#xff0c;那么很显然&#xff0c;我们需要用到我们学习这些&#xff0c;实现一个扫雷游戏。 扫雷游戏介绍以及玩法 在地…

idea git回滚之前提交记录

提交代码时&#xff0c;如果不小心提交了不需要提交的内容&#xff0c;在本地仓库中&#xff0c;此时需要回滚版本&#xff0c;如何回滚 1.打开git控制台&#xff0c;左下角git,选择要处理的分支&#xff0c;选择刷新获取最新git提交记录 2&#xff09;选中自己commit需要回滚…

计算机导论03-计算机组成

计算机系统结构 冯•诺依曼体系结构 冯•诺依曼体系结构的基本要点 冯•诺依曼思想即冯•诺依曼体系结构思想&#xff0c;其最基本的概念是存储程序概念&#xff0c;它奠定了现代计算机的结构基础。 功能部件: 计算机必须具备五大基本组成部件&#xff0c;包括&#xff1a;运…

【读书笔记】学习突围

最近在读一本书《学习突围》&#xff0c;作者是常青&#xff0c;知乎大V。对他的一些回答非常认同&#xff0c;受益匪浅&#xff0c;特此买来纸质书籍细细学习一番&#xff01; 1.【学习心态】&#xff08;拖延症、自控、执行力、专注力&#xff09; 2.【学习方法】&#xff0…

[后端] 微服务的前世今生

微服务的前世今生 整体脉络: 单体 -> 垂直划分 -> SOA -> micro service 微服务 -> services mesh服务网格 -> future 文章目录 微服务的前世今生单一应用架构特征优点&#xff1a;缺点&#xff1a; 垂直应用架构特征优点缺点 SOA 面向服务架构特征优点缺点 微服…

Vue入门四(组件介绍与定义|组件之间的通信)

文章目录 一、组件介绍与定义介绍定义1&#xff09;全局组件2&#xff09;局部组件 二、组件之间的通信1&#xff09;父组件向子组件传递数据2&#xff09;子传父通信 一、组件介绍与定义 介绍 组件(Component)是Vue.js 最强大的功能之一&#xff0c;它是html、css、js等的一个…

bootstrap搭建一个简单的官网案例附代码

bootstrap搭建一个简单的官网案例附代码 效果常用属性完整代码 效果 大概的效果如下 主要都是用bootstrap的代码实现的 网站是照着 b站视频做的 查看视频教程 建议自己先看一遍文档再跟着视频写&#xff0c;不然可能看不懂 bootstarp中文文档 logo是从别人的站上扒的有点不太协…

走进shell

Linux系统启动时&#xff0c;会自动创建多个虚拟控制台。虚拟控制台是运行在Linux系统内存中的终端会话。 打开Linux控制台Terminal使用tty命令查看当前使用的虚拟控制台。 注&#xff1a;tty 表示电传打字机(teletypewriter) $ tty /dev/pts/0表示当前使用的是/dev/pts/0 虚拟…