这个插件会读取项目根目录下的 package.json
文件来获取版本号,并记录当前的构建时间。
1. 插件代码 (version-info-plugin.js
)
在你的项目根目录(或者任何你方便引用的地方,例如 plugins/
文件夹)创建一个新文件,命名为 version-info-plugin.js
。
js
// version-info-plugin.js
const path = require('path');
const fs = require('fs');
// 如果需要获取 Git Commit Hash,可以引入 child_process
// const { execSync } = require('child_process');
class VersionInfoPlugin {
constructor(options = {}) {
this.options = {
filename: 'version.json', // 默认生成的文件名
// 你可以在这里添加更多选项,例如指定 package.json 的路径
// packageJsonPath: path.resolve(process.cwd(), 'package.json'),
...options
};
}
apply(compiler) {
// 1. 获取 package.json 中的版本信息
const packageJsonPath = path.resolve(compiler.context, 'package.json');
let packageVersion = 'N/A'; // 默认值,如果读取失败
try {
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonContent);
packageVersion = packageJson.version || 'N/A';
} catch (error) {
console.warn(
`[VersionInfoPlugin] 警告: 无法读取 package.json 文件或解析其内容。` +
`请确保文件存在且格式正确。路径: ${packageJsonPath}. 错误: ${error.message}`
);
}
// 2. 监听 Webpack 的 'emit' 钩子
// 'emit' 钩子在 Webpack 将所有资源输出到 output 目录之前触发。
// 这是一个异步钩子,所以我们使用 tapAsync。
compiler.hooks.emit.tapAsync(
'VersionInfoPlugin', // 插件名称,用于调试和错误报告
(compilation, callback) => {
// 3. 构建版本信息对象
const versionInfo = {
version: packageVersion,
buildTime: new Date().toISOString(), // ISO 8601 格式的构建时间
// 4. (可选) 获取 Git Commit Hash
// try {
// versionInfo.gitCommit = execSync('git rev-parse HEAD').toString().trim();
// } catch (gitError) {
// console.warn('[VersionInfoPlugin] 警告: 无法获取 Git Commit Hash。请确保项目是 Git 仓库。');
// versionInfo.gitCommit = 'N/A';
// }
};
// 将版本信息对象转换为格式化的 JSON 字符串
const jsonContent = JSON.stringify(versionInfo, null, 2); // null, 2 用于美化输出,2 个空格缩进
// 5. 将生成的 JSON 文件添加到 Webpack 的资源列表中
// compilation.assets 是一个对象,键是文件名,值是包含 source() 和 size() 方法的对象
compilation.assets[this.options.filename] = {
source: () => jsonContent, // source 方法返回文件内容
size: () => jsonContent.length, // size 方法返回文件大小
};
console.log(
`[VersionInfoPlugin] 已生成 ${this.options.filename} 文件。` +
`版本: ${versionInfo.version}, 构建时间: ${versionInfo.buildTime}`
);
// 6. 调用 callback,通知 Webpack 异步操作已完成
callback();
}
);
}
}
module.exports = VersionInfoPlugin;
2. webpack.config.js
配置
在你的 webpack.config.js
文件中引入并使用这个自定义插件。
js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 假设你使用了 html-webpack-plugin
const VersionInfoPlugin = require('./version-info-plugin'); // 引入你的自定义插件
module.exports = {
mode: 'production', // 或 'development'
entry: './src/index.js', // 你的入口文件
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true, // 每次构建前清理 dist 目录
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html', // 你的 HTML 模板文件
}),
// 实例化你的自定义插件
new VersionInfoPlugin({
// 可选:如果你想改变生成的文件名,例如:
// filename: 'app-build-info.json',
}),
],
devServer: {
static: path.resolve(__dirname, 'dist'), // 开发服务器静态文件目录
port: 8080,
open: true, // 启动后自动打开浏览器
},
};
3. package.json
示例
确保你的项目根目录有一个 package.json
文件,并且其中包含 version
字段。
json
{
"name": "my-frontend-app",
"version": "1.0.0", // 这个版本号会被插件读取
"description": "一个简单的前端应用",
"main": "src/index.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "webpack serve --config webpack.config.js"
},
"keywords": [],
"author": "Your Name",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.x.x",
"webpack": "^5.x.x",
"webpack-cli": "^5.x.x",
"webpack-dev-server": "^5.x.x"
}
}
4. 前端代码中如何访问 version.json
(src/index.js
和 public/index.html
)
在你的前端应用中,你可以通过 HTTP 请求(例如 fetch
)来加载这个 version.json
文件。
public/index.html
示例:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的前端应用</title>
</head>
<body>
<h1>欢迎来到我的应用</h1>
<p>应用版本: <span id="app-version">加载中...</span></p>
<p>构建时间: <span id="build-time">加载中...</span></p>
<!-- Webpack 会自动注入 bundle.js -->
</body>
</html>
src/index.js
示例:
js
// src/index.js
// 假设 version.json 会被输出到 dist 目录的根部
fetch('/version.json')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP 错误! 状态码: ${response.status}`);
}
return response.json();
})
.then(versionInfo => {
console.log('获取到的版本信息:', versionInfo);
document.getElementById('app-version').textContent = versionInfo.version;
// 格式化构建时间以便更好地显示
document.getElementById('build-time').textContent = new Date(versionInfo.buildTime).toLocaleString();
})
.catch(error => {
console.error('加载 version.json 失败:', error);
document.getElementById('app-version').textContent = '加载失败';
document.getElementById('build-time').textContent = '加载失败';
});
console.log('前端应用已启动!');
5. 运行和验证
-
确保你的项目结构如下:
bashmy-frontend-app/ ├── package.json ├── webpack.config.js ├── version-info-plugin.js ├── public/ │ └── index.html └── src/ └── index.js
-
安装所有依赖:
bashnpm install
-
运行构建命令:
bashnpm run build
-
构建完成后,检查
dist
目录,你会发现一个version.json
文件,内容类似:bash{ "version": "1.0.0", "buildTime": "2025-06-02T06:20:03.123Z" }
-
启动开发服务器:
bashnpm start
-
在浏览器中打开
http://localhost:8080
,你应该能看到页面上显示了从version.json
中读取到的版本号和构建时间。
这个插件提供了一个基础且实用的功能,你可以根据自己的需求进行扩展,例如添加 Git Commit Hash、构建环境信息等。