如何手写一个 webpack 插件:实现 vuecli3 打包时生成一个 git 分支版本信息的文件?

简介: 如何手写一个 webpack 插件:实现 vuecli3 打包时生成一个 git 分支版本信息的文件?

分析问题


  1. 首先需要我们获取项目当前所在分支的信息,比如项目打包时:当前的版本分支,最新代码提交人,时间,提交的信息
  2. 然后将这些信息生成到 txt 文本里面,这个文件是在打包的时候添加到打包目录里的



解决问题


先用 vuecli3 脚手架生成一个项目,在此基础上,我们在根目录新建一个 webpack-plugin 的文件夹,在这个文件夹里新建一个 branch-version-webpack-plugin.js 文件。如下图:

20210702175559866.png


1.获取 git 分支版本信息


参考下面的资料:


利用 node 的 api child_process 同步子进程获取分支信息:http://nodejs.cn/api/child_process.html

git pretty-formats:https://git-scm.com/docs/pretty-formats

Git语言 的 git show 命令: https://git-scm.com/docs/git-show


// 同步子进程
const execSync = require('child_process').execSync;
// 时间格式生成
function dateFormat(date) {
  let y = date.getFullYear();
  let M = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1;
  let d = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate();
  let h = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
  let m = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
  let s = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds();
  return `${y}-${M}-${d} ${h}:${m}:${s}`;
}
// 获取当前git分支信息
function getBranchVersionInfo() {
  // 当前分支名 git name-rev --name-only HEAD 这个命令会在终端输出你当前的版本或标签信息。
  let vName = execSync('git name-rev --name-only HEAD').toString().trim();
  // 提交的commit hash
  let commitHash = execSync('git show -s --format=%H').toString().trim();
  // 提交人姓名
  let name = execSync('git show -s --format=%cn').toString().trim();
  // 提交日期
  let date = dateFormat(new Date(execSync('git show -s --format=%cd').toString()));
  // 提交描述
  let message = execSync('git show -s --format=%s').toString().trim();
  return `
    当前分支名:${vName}\n
    提交的hash:${commitHash}\n
    提交人姓名:${name}\n
    提交日期:${date}\n
    提交描述:${message}
  `;
}



2.打包时文件生成

这个可以参考 html-webpack-plugin 插件的实现。


20210702181715542.png


重点看这个:Pushes the content of the given filename to the compilation assets.


20210702182054737.png


关于 hooks 使用 emit:输出目录之前执行。 https://v4.webpack.js.org/api/compiler-hooks/#emit

emit:


   AsyncSeriesHook

   Executed right before emitting assets to output dir.

   Callback Parameters: compilation


实现代码如下:


// 创建分支版本类
class BranchVersionWebpackPlugin {
  constructor(options) {
    // options 为调用时传的参数
    console.log('凯小默的 BranchVersionWebpackPlugin 被调用!', options);
  }
  /**
   * compiler: webpack 的实例 所有的内容
   * compilation: 本次打包的内容
   * */ 
  apply(compiler) {
    // 异步方法,生成打包目录时:生成文件
    compiler.hooks.emit.tapAsync('BranchVersionWebpackPlugin', (compilation, cb) => {
      // 添加分支版本信息文件
      let branchVersionInfo = getBranchVersionInfo();
      compilation.assets['version.txt'] = {
        source: () => branchVersionInfo,
        size: () => branchVersionInfo.length
      }
      cb();
    })
  }
}



完整代码使用

使用:我们找到我们的配置文件 vue.config.js 在里面添加下面代码:

// 分支版本信息
const BranchVersionWebpackPlugin = require('./webpack-plugin/branch-version-webpack-plugin');
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? '/dist/' : '/dist',
  // 将构建好的文件输出到哪里
  outputDir: 'dist',
  pages: {
    index: {
      entry: 'src/index/main.js',
      template: 'src/index/tpl.html',
      filename: 'index.html',
      title: 'kaimo 测试页',
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    }
  },
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      // 版本信息文件生成
      config.plugins.push(new BranchVersionWebpackPlugin());
    }
  }
};


branch-version-webpack-plugin.js 代码如下:

// 同步子进程
const execSync = require('child_process').execSync;
// 时间格式生成
function dateFormat(date) {
  let y = date.getFullYear();
  let M = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1;
  let d = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate();
  let h = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
  let m = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
  let s = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds();
  return `${y}-${M}-${d} ${h}:${m}:${s}`;
}
// 获取当前git分支信息
function getBranchVersionInfo() {
  // 当前分支名
  let vName = execSync('git name-rev --name-only HEAD').toString().trim();
  // 提交的commit hash
  let commitHash = execSync('git show -s --format=%H').toString().trim();
  // 提交人姓名
  let name = execSync('git show -s --format=%cn').toString().trim();
  // 提交日期
  let date = dateFormat(new Date(execSync('git show -s --format=%cd').toString()));
  // 提交描述
  let message = execSync('git show -s --format=%s').toString().trim();
  return `
    当前分支名:${vName}\n
    提交的hash:${commitHash}\n
    提交人姓名:${name}\n
    提交日期:${date}\n
    提交描述:${message}
  `;
}
// 创建分支版本类
class BranchVersionWebpackPlugin {
  constructor(options) {
    // options 为调用时传的参数
    console.log('凯小默的 BranchVersionWebpackPlugin 被调用!', options);
  }
  /**
   * compiler: webpack 的实例 所有的内容
   * compilation: 本次打包的内容
   * */ 
  apply(compiler) {
    // 异步方法,生成打包目录时:生成文件
    compiler.hooks.emit.tapAsync('BranchVersionWebpackPlugin', (compilation, cb) => {
      // 添加分支版本信息文件
      let branchVersionInfo = getBranchVersionInfo();
      compilation.assets['version.txt'] = {
        source: () => branchVersionInfo,
        size: () => branchVersionInfo.length
      }
      cb();
    })
  }
}
module.exports = BranchVersionWebpackPlugin;




测试结果

添加好之后我们执行打包命令:

npm run build


控制台打包成功,undefined 表示使用插件没有传参。

20210702183810647.png


然后我们看一下 dist 打包目录是否生成 version.txt 文件:发现是有的,如下图所示

2021070218402463.png


接下来我们提交一下代码:然后在打包看看:发现信息已经更新了,当然你也可以切换分支测试一下。


20210702184257533.png





目录
相关文章
|
2月前
|
开发工具 git
使用Git根据日期进行代码版本切换的方法
通过以上步骤,可以有效地根据日期进行Git代码版本的切换。这种方法在需要回溯历史版本进行bug修复或功能复查时特别有用。Git的灵活性和强大功能使其成为现代软件开发不可或缺的工具之一。
319 103
|
6月前
|
存储 安全 开发工具
深度解决 Git “fatal: refusing to merge unrelated histories” 错误解析什么是历史分支优雅草卓伊凡
深度解决 Git “fatal: refusing to merge unrelated histories” 错误解析什么是历史分支优雅草卓伊凡
546 4
深度解决 Git “fatal: refusing to merge unrelated histories” 错误解析什么是历史分支优雅草卓伊凡
|
3月前
|
开发工具 git
Git版本控制工具合并分支merge命令操作流程
通过以上步聚焦于技术性和操作层面指南(guidance), 可以有效管理项目版本控制(version control), 并促进团队协作(collaboration).
532 15
|
5月前
|
开发工具 git
使用Git下载指定版本或指定commit
使用Git下载指定版本或指定commit
|
10月前
|
开发工具 git 开发者
vscode+git解决远程分支合并冲突
通过这些详细步骤,您可以掌握如何使用VSCode和Git高效地解决远程分支合并冲突,提高开发效率和代码质量。希望这些内容对您的学习和工作有所帮助。
2408 86
|
9月前
|
安全 开发工具 Android开发
【Android Git】Git版本回退方式
在实际操作中,选择合适的版本回退方式,可以有效地管理代码版本,提高开发效率和代码质量。
543 26
|
9月前
|
IDE 开发工具 git
pycharm如何查看git历史版本变更信息
通过上述步骤,你可以在 PyCharm 中轻松查看 Git 的历史版本变更信息,无论是针对整个项目、特定文件还是分支。使用 PyCharm 的 Git 集成功能,可以更高效地管理和审查代码变更,提高开发过程的透明度和可维护性。
660 19
|
11月前
|
存储 缓存 Java
图解Git——远程分支《Pro Git》
远程分支是 Git 中用于管理分布式协作的关键概念。远程引用指向远程仓库中的分支和标签,常用 `git ls-remote` 或 `git remote show` 查看。日常开发中,通常使用远程跟踪分支(如 `origin/main`)与远程分支交互,简化远程仓库状态的管理和使用。远程跟踪分支记录远程分支的状态,但本身只读。
263 6
|
JSON 开发工具 git
git rebase 合并当前分支的多个commit记录
git rebase 合并当前分支的多个commit记录
881 1
|
开发工具 git
【Git】一文带你入门Git分布式版本控制系统(创建合并分支、解决冲突)
【Git】一文带你入门Git分布式版本控制系统(创建合并分支、解决冲突)
254 0
【Git】一文带你入门Git分布式版本控制系统(创建合并分支、解决冲突)