文章首发地址:https://juejin.cn/post/7472684607365922850
插件配景及项目概述
在现代前端开发中,我们常常需要获取当前线上情况的代码构建信息,如项目打包人、打包时间、Git版本信息等。在持续集成/持续交付(CI/CD)流水线中,这类信息尤其重要。来看一下几个真实的开发场景:
- 主动构建与部署的困扰:公司的项目基于GitLab和Coding流水线举行主动构建和部署。每当开发人员提交代码后,测试同学常常询问“代码更新了吗?为什么没有生效?”此时,我不得不登录到Coding查察仓库,确认是否是最新代码。
- 版本号的查找贫苦:每次发布版本时,都需要手动填写Git版本号,而这往往意味着我得登录Coding查找相干信息,过程繁琐且容易堕落。
- 生产问题排查的低效:当生产代码出现问题时,前端A与运维B之间需要反复确认线上镜像和对应代码信息,找到匹配的版本后才能开始排盘问题。这个过程非常低效且浪费时间。
假如我们能开发一个插件,主动记录每次打包的代码信息,而且能在生产和开发情况中追踪这些信息,是否能完美解决上述问题呢?dist-info插件应运而生!
dist-info是一款可以大概将Git信息或自定义内容注入HTML的插件,兼容Webpack和Vite项目。使用该插件后,只需在浏览器控制台输入info,即可轻松查察代码的相干信息或自定义内容。
本文将使用字节最新推出的**AI编程工具Trae**,通过零代码方式快速搭建插件框架、编写焦点代码,完成插件的开发工作。开发完成后,我们将借助Trae将插件上传至GitHub,并在npm上发布,确保插件的高效分发与便捷使用。
为什么选择Trae
Trae是字节最新推出的一款免费AI编程IDE,对标国外的Cursor、Copilot这类AI编程工具。
Trae(/treɪ/)与 AI 深度集成,提供智能问答、代码主动补全以及基于 Agent 的 AI 主动编程能力。使用 Trae 开发项目时,我们可以与 AI 机动协作,提拔开发服从。
由于是国产的,在语言和易用性方面更加符合国产编程宝宝的体质。假如你是一个Vscode忠实用户,可以无缝迁移至Trae。
官方先容:https://docs.trae.ai/docs/what-is-trae?_lang=zh
使用Trae实现dist-info插件
开发前准备
Trae支持mac和windows版本,我们根据官方的下载地址安装软件。安装Trae时,我们可以选择主题颜色,然后同步我们的Vsocde设置。
Trae的编译器界面与Vscode基本是同等的,同步Vsocde设置后,Trae的左侧栏也会主动展示我们Vscode安装的插件,这可以让我们无缝从Vsocde上手Trae。
注:假如下载软件后无法使用,登录Vpn科学上网后再使用。
插件实现原理
要实现插件的结果,我们的大致思路如下:
- 打包或编译时,通过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直接在空项目中创建上述项目结构,我们给出必要提示:
我要开发一个名为dist-info的前端插件,文件的焦点逻辑位于根目录的index.js。插件使用rollup举行打包,打包输出的目录为lib/index.js。请帮我初始化git信息、安装设置好项目用到的rollup依赖(设置写在rollup.config.js文件中)。
Trae-Builder会根据提示,主动帮我创建项目,生成对应的项目文件。
在项目生成过程中,我们可以根据需求实行对应的命令,参考下图,实行git commi
Trae-Builder运行完毕后,一个完成的项目就被快速创建出来了。现在,我们只需要查察项目,生存删减代码即可。
如下图,Trae-Builder生成的代码基本完全满足我的需求,直接点击【担当】即可。
至此,我们借助Trae-Builder就快速实现了项目的搭建。
使用Trae实现焦点代码
Trae-Chat简介
Trae提供了一个Trae-Chat模式,它可以对我们的代码或编程问题举行提问。通过Trae-Chat,可以极大提拔开发服从。
代码基本架构
根据插件的需求,我们的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中。
有些同学大概不太懂isVite的逻辑,借助Trae-Chat回答一下:
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生成的时间是原始数据类型,我们可以将时间举行格式化,方便阅读。
Trae集成了根据注释生成代码的功能,我们可以借助这一功能继续完满代码。
- {
- description: "提交时间",
- value: getDate(getGitInfo("git show -s --format=%cd")),
- },
复制代码 网页端的信息输出与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中实现注入,这一过程的实现要根据不同的脚手架类型做不同处置惩罚。同样的,我们借助Trae-Builder快速补全代码

根据生成结果,我们稍微优化下代码
- 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插件开发文章。

由于vite提供了transformIndexHtml钩子
将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插件入门教程
结果验证
插件开发完毕后,我们可以在恣意一个webpck5或vite项目中引入index.js中的代码,查察结果。
如图,在webpack项目中引入代码(distInfo就是开发的插件代码)
然后启动项目,打开控制台,输入“info”可以看到,打包的信息已经实现了。
如图,在vite项目中引入代码(distInfo就是开发的插件代码)
启动项目后,输入指令“info”也可以看到git信息。
代码优化
通过上述的代码,我们已经实现了一个功能完备的网站打包信息追踪插件,但它还不完满,以下是一些可以改进的地方:
生成的js脚本是明文的,这意味着用户的git信息也会被明文展示,这显然是不安全的。
为了解决上述问题,我们可以对生成的信息在编译时加密,运行时解密。
直接通过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的美化教程
根据基础代码,我们只能通过在控制台输入"info"触发信息打印,而且不可以大概自定义输出信息。因此,我们可以给BuildInfoPlugin插件增长options设置项即可。
- function BuildInfoPlugin(options = {}) {
- try {
- const jsContent = getJsContent(options);
- return isVite ? vitePlugin(jsContent) : webpackPlugin(jsContent);
- } catch (err) {
- console.log('BuildInfo', err);
- }
- }
复制代码 篇幅问题,不在此文章中具体展示优化过程,感爱好的同学可以直接fork源码。
源码地址:https://github.com/1139874527/dist-info
github上传与发包
插件开发完毕后,我们可以将代码上传至gitub或直接以npm包的形式发布供其他开发者使用。
使用Trae关联github仓库
要将代码上传至github,我们首先要在github创建一个仓库
然后,根据提示在Trae中实行响应的git命令即可。
npm发包
为了能让其他小同伴使用我们开发的插件,我们可以将代码发布至npm。发包之前,我们需要先注册一个npm账号。注册好后,我们在Trae的控制台输入npm login举行账号登录。
根据提示,我们回车后会打开网页举行npm登录
登录后,我们在Trae的控制台输入npm publish,出现下图的输出信息后即可发布乐成。
总结
插件概述
在本文中,我们通过Trae实现了dist-info插件的开发。dist-info是一个兼容Webpack 5和Vite项目的前端插件,可以大概将Git信息或自定义内容注入到HTML文件中。使用该插件后,我们可以直接在浏览器控制台查察相干信息,提拔开发和调试服从。
它的使用非常简单:
在webpack项目中使用
- const DistInfo = require("dist-info");
- module.exports = {
- // ...
- plugins: [
- new DistInfo()
- ],
- };
复制代码 在vite项目中使用
- import { defineConfig } from 'vite';
- import distInfo from 'dist-info';
- export default defineConfig({
- plugins: [distInfo()],
- });
复制代码 假如你想自定义插件行为,可以查察发布在npm上的插件使用教程。
项目github仓库地址:https://github.com/1139874527/dist-info,欢迎各位star。
Trae的开发表现
Trae的优势
在本文的插件开发过程中,项目框架的生成和焦点代码的编写险些完全依赖于Trae的Builder模式和Chat模式。团结Trae独特的注释生成代码功能,我们显著提拔了开发服从,这一过程甚至逾越了传统的VScode开发体验。
- Builder模式:通过Trae的Builder模式,我们可以大概快速搭建项目框架和设置,省去了繁琐的手动设置和初始化项目过程,极大提高了开发的启动速率。别的,Builder模式也可以根据我们的要求快速完成代码片断的编写,真正实现了“中文”编程的过程。
- Chat模式:Trae的Chat模式不仅能实时解答开发中的编程问题,还能团结我们项目中的代码片断给出对应代码问题的解决方案,大大简化了开发过程中的决策和编码环节。
- 注释生成代码:Trae的注释生成代码功能可以主动根据我们在代码中添加的注释来生成相应的代码,实现从文档到代码的快速转化,进一步提高了开发的主动化和服从。
这些功能的团结,使得Trae在提高开发服从方面远远逾越了传统的VScode。对于一款AI编程工具来说,Trae的表现是非常合格的!它完全可以媲美国外的Cursor、Copilot这类AI编程工具,而且它目前是免费的!
与Vscode比较
由于Trae在实现方式和界面上与VSCode相似,很多人大概会问,Trae是否可以大概代替VSCode?
事实上,Trae与VSCode的产品定位有所不同。Trae是AI加强版的编程工具,专注于AI,而VSCode是一款成熟的代码编辑器,强调功能性。因此,Trae和VSCode并不是替代关系,而是可以相辅相成,共同发展。
假如我们剔除AI功能,仅就编程工具本身举行比较,我的回答是:目前Trae还无法完全代替VSCode。
相比VSCode,Trae在以下方面存在不敷:
- 生态系统:VSCode有超过5万个插件,涵盖各种开发场景,而Trae的插件兼容性尚未达到这个水平。
- 稳定性:VSCode颠末多年发展,已被全球开发者验证,而Trae作为新产品,稳定性仍待考验。
- 用户群体:VSCode月活泼用户超过1500万,社区支持强大,Trae的用户基数较小,解决方案积累不敷。
- 高级功能:VSCode支持远程开发、Docker集成等,而Trae更多侧重代码生成,缺乏深度调试和复杂设置工具。
综上,我以为Trae作为一个代码生成、优化工具,我觉得它拥有巨大潜力,是非常合格好用的。但作为一个编程工具而言,在性能和生态兼容性方面,当前仍无法全面代替VSCode。
参与项目与代码贡献
本文中提到的插件已经基本完满,而且稳定,可以供大家使用。目前,插件已发布至npm,欢迎安装使用。dist-info是一个简单而值得学习的项目,它仍有不少优化空间。假如你有爱好参与维护并成为贡献者,欢迎 |