前端项目构建打包生成Git信息文件的作用是将当前代码所属的Git仓库的相关信息(例如commit hash、branch name、commit message等)保存在项目中的一个文件中。这样做的目的是为了方便在程序中获取和展示当前代码的版本信息,以及方便对项目进行版本管理和追踪。
首先我们需要在项目中安装四个需要的npm包
作用:提供了文件系统相关的功能,允许你在Node.js环境中对文件进行读取、写入、修改、删除等操作。。 用于生成最后的信息文件
安装方式如下
npm install fs --save-dev
或
pnpm add --save-dev
或
yran install fs --save-dev
是一个用于创建子进程的模块。它提供了一些方法来执行外部命令、创建子进程,并与其进行通信。
安装方式如下
npm install child_process --save-dev
或
pnpm child_process --save-dev
或
yran install child_process --save-dev
os包可以让开发者在Node.js环境中访问操作系统相关的功能。
安装方式如下
npm install os --save-dev
或
pnpm os --save-dev
或
yran install os --save-dev
os包的方法
npm install path --save-dev
或
pnpm path --save-dev
或
yran install path --save-dev
在项目的根目录文件下创建 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('打包完成');
}
});
}
我这里是用vue项目为例子 React、Angular 项目也是差不多的做法
打开项目根目录下的 package.json文件 将scripts下的build 改成
node automated_scripts/build.js
如下图
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();