稀土掘金技术社区 2小时前
写了个插件,给代码里藏东西,线上可用!
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了一款能够自动记录和注入代码Git信息的插件,方便开发者在代码中嵌入自定义信息,例如部署文档和构建时间等。该插件兼容Webpack和Vite项目,通过在浏览器控制台输入“info”即可查看构建信息。文章详细阐述了插件的实现原理、Trae-Builder的使用、核心代码构建以及Webpack和Vite的适配方案。此外,还探讨了信息加密、console美化和增加配置项等优化措施,并提供了插件的npm包和GitHub仓库地址。

💡 插件的核心功能在于自动捕获Git信息,并将这些信息注入到打包后的代码中,从而方便开发者追踪代码的构建状态和关联信息。

🛠️ 插件通过node环境获取Git信息,并根据不同的构建工具(Webpack或Vite)采用不同的方式将信息注入到HTML文件中。

🔑 通过对`window.info`属性进行劫持,插件实现了在浏览器控制台中以特定方式展示Git信息的功能,用户只需在控制台输入“info”即可查看。

🛡️ 为了增强安全性,文章提出了对Git信息进行加密的优化方案,防止敏感信息泄露。

🎨 为了提升用户体验,文章还介绍了通过美化console输出和增加配置项来优化插件的展示效果和可定制性。

原创 石小石Orz 2025-05-29 08:30 重庆

点击关注公众号,“技术干货”及时达!

插件用途

大家好,我是石小石!

相信你一定也遇到过这样的场景:有时候我们想在代码中 “夹带一点私货”,比如留下一些自定义信息或标识,如部署文档、关联资料、构建时间等信息,让这些内容跟着上线代码一并部署。当然,这些信息的查看方式只有我们知道,这样的话,代码开发会方便不少!

基于这个想法,我开发了一个小插件,能够自动记录当前代码的 Git 信息,还可以注入任意自定义内容,同时兼容 Webpack 和 Vite 项目。

使用这个插件后,只需要在浏览器控制台输入 

info

,就能轻松查看代码中的构建信息或你的专属小彩蛋啦!

使用 Trae 实现插件

插件原理

要实现插件的效果,我们的大致思路如下:

    打包或编译时,通过 node 获取当前的 git 信息

    打包结束后,将获取的 git 信息注入打包后的代码中

    在浏览器控制台,通过特殊方式展示打包信息

├── 核心逻辑层│   ├── Git信息采集(借助node能力)│   ├── 信息处理与注入(通过webapck或vite钩子实现)├── 构建工具适配层(判断构建工具类型)│   ├── Webpack插件实现│   └── Vite插件实现└── 输出呈现层    ├── 控制台样式优化(console美化)    └── 信息展示机制(window劫持)

使用 Trae-Builder 快速搭建项目

在开始项目之前,我们先创建 dist-info 文件夹,然后用 Trae 打开项目。

要开发一个 webpack 或 vite 插件,我们的项目应该包含下面的结构:

├── index.js           // 插件核心逻辑├── README.md          // 插件使用说明├── rollup.config.js   // 打包配置├── package.json       // 依赖管理

Trae 提供了一个 「Trae-Builder 模式」,可以轻松完成从零到一的项目构建。在 「Builder 模式」下,我们对代码文件的任何更改都会自动保存。

我们可以借助 「Trae-Builder」 直接在空项目中创建上述项目结构

Trae-Builder 运行完毕后,一个完成的项目就被快速创建出来了。现在,我们只需要审查项目,保留删减代码即可。如下图,Trae-Builder 生成的代码基本完全满足我的需求,直接点击【接受】即可。

至此,我们借助 Trae-Builder 就快速实现了项目的搭建。

使用 Trae 实现核心代码

    代码基本架构

根据插件的需求,我们的 index.js 基本架构应该如下:

const isVite =  process.argv.some((arg) => arg.includes("vite")) ||  process.env.VITE_ !== undefined;function DistInfoPlugin() {  try {    //获取js内容(内部包含git信息)    const jsContent = getJsContent();    // 根据脚手架类型,执行不同js注入逻辑    return isVite ? vitePlugin(jsContent) : webpackPlugin(jsContent);  } catch (err) {    console.log("DistInfoPlugin", err);  }}// 确保插件作为默认导出module.exports.default = DistInfoPlugin;module.exports = DistInfoPlugin;

当项目打包时,插件会判断当前脚手架类型,执行 webapck 或 vite 对应的钩子函数。打包过程中,node 会获取当前的 git 信息,并生成 js 内容(getJsContent)。在打包结束时,对应的 webapck 或 vite 钩子激活,生成的 js 脚本被注入在打包文件的 index.html 中。

    git 信息的获取

getJsContent 的第一步应该是通过 node 获取 git 信息,我们通过 Trae-Builder 让 Trae 帮我们完善代码

Trae-Builder 生成的代码基本可用,我们接受修改后的代码,然后做适当修改:

const { execSync } = require('child_process') //同步子进程const getGitInfo = (gitMeta) => {  try {    return execSync(gitMeta)?.toString().trim();  } catch {    return "--";  }};const getJsContent = () => {  const consoleList = [    {      description: "提交人员",      value: getGitInfo("git show -s --format=%cn"),    },    {      description: "版本信息",      value: getGitInfo("git show -s --format=%h"),    },    {      description: "代码分支",      value: getGitInfo("git symbolic-ref --short -q HEAD"),    },    {      description: "提交说明",      value: getGitInfo("git show -s --format=%s"),    },    {      description: "提交时间",      value: getGitInfo("git show -s --format=%cd"),    },  ];};

上述代码的核心功能是通过 

child_process

 模块执行 Git 命令,并提取 Git 信息。

child_process

 是 Node.js 的一个核心模块,允许你、我们在 Node.js 中启动子进程并与之进行交互。

execSync(gitMeta)

 执行传入的 Git 命令,返回的是一个 「Buffer」 对象,通过 

.toString()

 将其转换为字符串。

由于 git show 生成的时间是原始数据类型,我们可以将时间进行格式化,方便阅读。

    网页端的信息输出与 js 生成

把代码的打包信息直接输出在控制台是不安全的,我们并不希望所有人打开控制台都可以看到打包信息。参考 vue2 的数据劫持原理,我们可以对 window 对象的特殊属性进行数据劫持:

Object.defineProperty(window, 'info', {  get: function() {    // console.log("window的info属性被访问了")  }})

根据上述代码的效果,当我们读取 window 的 info 属性时(相当于控制台输入 info),会触发 getter 的回调函数。

那么,如果我们在 get 的方法中输出所有的 git 信息,然后将这段 js 注入打包后的 index.html,就可以实现如下效果了

在控制台输入 "info",控制台打印代码的 git 信息。

根据上述原理,我们的 getJsContent 方法完善如下:

const getJsContent = () => {  const consoleList = [    // ...  ];  return `(function(window){    const BUILD_INFO_CONSOLE_LIST = ${consoleList}    Object.defineProperty(window, 'info', {        get: function() {            console.clear();            BUILD_INFO_CONSOLE_LIST.forEach(res=>{                console.log (res.description, res.value)             })        }    })})(window)`;};

    打包完成时的 js 脚本注入

我们插件的最后一步就是将生成的 js 脚本,在打包完毕后插入项目的 index.html 中实现注入,这一过程的实现要根据不同的脚手架类型做不同处理。

function webpackPlugin(jsContent) { const createAsset = (content) => { return { source: () => content, size: () => content.length } } return { apply(compiler) { compiler.hooks.emit.tap('distInfoPlugin', (compilation) => { // 获取 HTML 和 JS 文件的路径 const jsAsset = Object.keys(compilation.assets).find((assetPath) => assetPath.endsWith('.js')) const htmlAsset = Object.keys(compilation.assets).find((assetPath) => assetPath.endsWith('.html')) if (!jsAsset || !htmlAsset) return // 生成唯一的 JS 文件路径 const jsPathParts = jsAsset.split('/') const timestamp = Date.now().toString() jsPathParts[jsPathParts.length - 1] = `dist-info-${timestamp}.js` const jsFilePath = jsPathParts.join('/') // 修改 HTML 文件内容,插入新的 JS 文件路径 const originalHtmlContent = compilation.assets[htmlAsset]?.source() if (!originalHtmlContent) return const updatedHtmlContent = originalHtmlContent.replace( /(<head[^>]*>)/, `$1<script src="${compiler.options.output.publicPath}${jsFilePath}"></script>` ) // 更新 HTML 文件内容到编译输出 compilation.assets[htmlAsset] = createAsset(updatedHtmlContent) compilation.assets[jsFilePath] = createAsset(jsContent) }) } }}

上面的代码实现了一个自定义的 Webpack 插件,用于在构建时处理 HTML 和 JavaScript 文件的输出,并动态地插入一个新的 JavaScript 文件到 HTML 中。

上面的代码使用到了 webpack 插件开发的一些基础知识,如果有疑问,可以参考博主的 webpack 插件开发文章[1]

    vite 脚本插入

由于 vite 提供了 transformIndexHtml 钩子[2]

将 js 注入到打包后的 html 中是非常容易的

function vitePlugin(jsContent) {  return {    name: "vite-plugin-dist-info",    transformIndexHtml(html) {      const scriptTag = `<script>${jsContent}</script>`;      return html.replace(/</body>/, `${scriptTag}</body>`);    },  };}

如果你对 vite 的插件有疑问,可以参考博主的 vite 插件入门教程[3]

    效果验证

插件开发完毕后,我们可以在任意一个 webpck5 或 vite 项目中引入 index.js 中的代码,查看效果。

    webpack 项目

如图,在 webpack 项目中引入代码(distInfo 就是开发的插件代码)

然后启动项目,打开控制台,输入 “info” 可以看到,打包的信息已经实现了。

    vite 项目

如图,在 vite 项目中引入代码(distInfo 就是开发的插件代码)

启动项目后,输入指令 “info” 也可以看到 git 信息。

代码优化

通过上述的代码,我们已经实现了一个功能完备的网站打包信息追踪插件,但它还不完善,以下是一些可以改进的地方:

    信息加密

生成的 js 脚本是明文的,这意味着用户的 git 信息也会被明文展示,这显然是不安全的。

为了解决上述问题,我们可以对生成的信息在编译时加密,运行时解密。

    console 美化

直接通过 console.log 输出的信息不够醒目,在控制台与普通打印文本不好区分。我们可以通过重写 log 方法实现输出信息的美化:

function log (description, value) {  console.log(    "%c 信息名称 %c 信息值 ",    "background:#ff4d4f;border:1px solid #ff4d4f; padding: 1px; border-radius: 2px 0 0 2px; color: #fff",    "border:1px solid #ff4d4f; padding: 1px; border-radius: 0 2px 2px 0; color: #ff4d4f",  )}

参考博主的 console.log 的美化教程[4]

    增加配置项

根据基础代码,我们只能通过在控制台输入 "info" 触发信息打印,而且不能够自定义输出信息。因此,我们可以给 BuildInfoPlugin 插件增加 options 配置项即可。

function BuildInfoPlugin(options = {}) {    try {        const jsContent = getJsContent(options);        return isVite ? vitePlugin(jsContent) : webpackPlugin(jsContent);    } catch (err) {        console.log('BuildInfo', err);    }}

篇幅问题,不在此文章中具体展示优化过程,感兴趣的同学可以直接 fork 源码。

源码地址:github.com/1139874527/…[5]

参与项目与代码贡献

本文中提到的插件已经基本完善,并且稳定,可以供大家使用。目前,插件已发布至 npm,欢迎安装使用。

dist-info

是一个简单而值得学习的项目,它仍有不少优化空间。如果你有兴趣参与维护并成为贡献者,欢迎🌟star 并提交 PR(合理必通过)。

插件使用地址:www.npmjs.com/package/dis…[6]

github 仓库地址:github.com/1139874527/…[7]


关注更多AI编程资讯请去AI Coding专区:https://juejin.cn/aicoding

""~

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

插件开发 Webpack Vite Git信息 代码构建
相关文章