一个小小的webpack插件

这个插件会读取项目根目录下的 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.jspublic/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. 运行和验证

  1. 确保你的项目结构如下:

    bash 复制代码
    my-frontend-app/
    ├── package.json
    ├── webpack.config.js
    ├── version-info-plugin.js
    ├── public/
    │   └── index.html
    └── src/
        └── index.js
  2. 安装所有依赖:

    bash 复制代码
    npm install
  3. 运行构建命令:

    bash 复制代码
    npm run build
  4. 构建完成后,检查 dist 目录,你会发现一个 version.json 文件,内容类似:

    bash 复制代码
    {
      "version": "1.0.0",
      "buildTime": "2025-06-02T06:20:03.123Z"
    }
  5. 启动开发服务器:

    bash 复制代码
    npm start
  6. 在浏览器中打开 http://localhost:8080,你应该能看到页面上显示了从 version.json 中读取到的版本号和构建时间。

这个插件提供了一个基础且实用的功能,你可以根据自己的需求进行扩展,例如添加 Git Commit Hash、构建环境信息等。

相关推荐
小小小小宇2 小时前
虚拟列表兼容老DOM操作
前端
悦悦子a啊2 小时前
Python之--基本知识
开发语言·前端·python
安全系统学习3 小时前
系统安全之大模型案例分析
前端·安全·web安全·网络安全·xss
涛哥码咖3 小时前
chrome安装AXURE插件后无效
前端·chrome·axure
OEC小胖胖4 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水4 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐4 小时前
零基础学HTML和CSS:网页设计入门
前端·css
老虎06274 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
灿灿121384 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css
烛阴5 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript