news 2026/5/15 8:03:36

基于Vite与TypeScript的油猴脚本工程化开发实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Vite与TypeScript的油猴脚本工程化开发实战

1. 项目概述:一个浏览器脚本的“瑞士军刀”启动器

如果你经常在浏览器里折腾,想给各种网页加上自己的“魔法”,比如让ChatGPT的网页版用起来更顺手,或者想自动化一些重复的网页操作,那你大概率听说过油猴脚本。但很多时候,我们找到的脚本要么功能太单一,要么配置起来很麻烦,想自己动手改改,又觉得从零开始写一个油猴脚本的架子太费劲。今天要聊的这个项目,KudoAI/chatgpt.js-greasemonkey-starter,就是来解决这个痛点的。它不是一个成品脚本,而是一个功能强大、开箱即用的油猴脚本开发模板,或者说是一个“启动器”。

简单来说,这个项目为你搭建好了一个现代化的油猴脚本开发环境。它内置了与ChatGPT网页版深度集成的核心库chatgpt.js,提供了实时热重载、TypeScript支持、代码风格检查、自动构建和发布等一整套开发工具链。你不再需要从零开始配置构建工具、处理模块依赖,或者手动管理脚本的元信息。这个启动器让你可以专注于脚本的核心逻辑,快速实现诸如“一键总结长文章”、“批量导出对话历史”、“自定义快捷指令”等功能,并且能享受到现代前端开发的流畅体验。

它适合谁呢?首先,是那些想为ChatGPT网页版开发增强功能,但又不想重复造轮子的开发者。其次,是任何希望快速启动一个高质量、可维护的油猴脚本项目的爱好者。即使你对构建工具不太熟悉,这个项目预设的配置也能让你轻松上手。接下来,我会带你深入拆解这个启动器的设计思路、核心功能,并分享如何用它从零开始打造一个属于自己的网页增强脚本。

2. 核心架构与设计思路拆解

2.1 为什么需要这样一个“启动器”?

传统的油猴脚本开发,通常是在油猴插件的编辑器里直接写一个巨大的.user.js文件。这种方式在脚本简单时没问题,但一旦功能复杂,就会暴露出很多问题:代码难以组织和维护、缺乏现代语法特性(如ES模块、TypeScript)、调试困难、没有版本管理和构建流程。chatgpt.js-greasemonkey-starter的出现,正是为了将油猴脚本开发带入工程化时代。

它的核心设计思路是“约定大于配置”和“开箱即用”。项目作者预判了开发一个与ChatGPT交互的脚本所需的常见需求:需要一个强大的底层API库来可靠地操作ChatGPT的DOM和状态(chatgpt.js),需要一个高效的本地开发环境(热重载),需要类型安全来提高开发效率(TypeScript),需要代码质量保障(ESLint/Prettier),以及需要一键打包发布的能力。这个启动器把这些分散的、需要手动集成的环节,通过一套预设的构建配置(基于Vite)完美地串联了起来。

注意:这里说的“工程化”,并不是要把它搞得很复杂,而是通过工具让开发变得更简单、更可靠。就像你用现成的面团做面包,总比自己从种小麦开始要快得多、好得多。

2.2 技术栈选型背后的逻辑

让我们看看这个项目都用了哪些技术,以及为什么选它们:

  1. Vite:作为构建工具。Vite以极快的冷启动和热更新速度著称,这对于需要频繁修改并实时在浏览器中查看效果的脚本开发来说,是至关重要的体验提升。它原生支持ES模块,能完美处理油猴脚本所需的依赖打包。
  2. TypeScript:作为开发语言。操作网页DOM,尤其是像ChatGPT这样结构可能变化的复杂应用,类型提示能极大减少错误,提高代码智能补全能力,让开发过程更顺畅。
  3. chatgpt.js:作为核心运行时库。这是同一个作者维护的另一个明星项目,它封装了与ChatGPT网页版交互的所有复杂细节,提供了稳定、高层的API。使用它,你不需要再去研究ChatGPT前端代码的DOM结构变化,直接调用诸如sendMessage,getConversationHistory这样的方法即可,大大降低了开发门槛和脚本的脆弱性。
  4. ESLint + Prettier:代码检查和格式化工具。保证团队协作或个人长期维护时代码风格的一致性,提前发现潜在错误。
  5. @grant@require的自动化管理:油猴脚本头部的元数据(如@grant GM_xmlhttpRequest)和外部库依赖声明,在构建过程中会自动从代码分析和package.json中提取并注入到最终的用户脚本中,开发者无需手动维护,避免了遗漏。

这个技术栈组合,瞄准的就是“开发体验”和“脚本质量”这两个核心目标。它不是最炫技的堆砌,而是每一个选择都切实解决了油猴脚本开发中的一个具体痛点。

3. 环境准备与项目初始化实操

3.1 前置条件检查

在开始之前,你需要确保本地环境已经准备好:

  • Node.js:版本建议在 16 或 18 以上。你可以通过在终端运行node -v来检查。
  • 包管理器npmyarnpnpm。项目通常使用npm,但pnpm因其速度快和磁盘效率高,是很多现代项目的推荐选择。你可以根据喜好安装。
  • 浏览器与油猴插件:任何支持用户脚本的浏览器(Chrome, Firefox, Edge等),并安装好 Tampermonkey 或 Violentmonkey 插件。这是脚本最终运行的环境。

3.2 克隆与安装

打开你的终端,执行以下步骤:

# 1. 克隆项目到本地 git clone https://github.com/KudoAI/chatgpt.js-greasemonkey-starter.git # 或者使用 GitHub CLI # gh repo clone KudoAI/chatgpt.js-greasemonkey-starter # 2. 进入项目目录 cd chatgpt.js-greasemonkey-starter # 3. 安装项目依赖 # 使用 npm npm install # 或使用 pnpm (推荐,更快) pnpm install

安装过程会下载 Vite、TypeScript、chatgpt.js 以及其他所有开发依赖。这个过程通常很快,取决于你的网络速度。

3.3 项目结构初探

安装完成后,用你喜欢的代码编辑器(如 VS Code)打开项目文件夹。你会看到类似如下的结构:

chatgpt.js-greasemonkey-starter/ ├── src/ │ ├── main.ts # 脚本的主入口文件,你的核心逻辑从这里开始写 │ └── vite-env.d.ts # Vite 环境类型声明 ├── dist/ # 构建后生成的目录,最终的 `.user.js` 文件在这里 ├── package.json # 项目配置和依赖声明 ├── vite.config.ts # Vite 构建配置文件 ├── tsconfig.json # TypeScript 配置文件 ├── .eslintrc.json # ESLint 代码检查规则 ├── .prettierrc # Prettier 代码格式化规则 └── README.md # 项目说明文档

对于初学者,你最需要关注的是src/main.ts文件。这是你编写脚本功能的地方。vite.config.ts包含了构建为油猴脚本的所有魔法,初期一般不需要修改。

4. 核心开发流程详解

4.1 理解入口文件:src/main.ts

让我们打开src/main.ts,看看它的初始内容。它通常包含以下几个关键部分:

  1. 导入chatgpt.jsimport { ChatGPTAPI } from 'chatgpt.js';这行代码引入了核心库。
  2. 定义主函数:一个main()函数,这是脚本执行的起点。
  3. 使用chatgpt.jsAPI:在main()函数内,会实例化ChatGPTAPI,并调用其方法。初始模板可能会有一个简单的示例,比如等待ChatGPT界面加载完成,然后在某个位置添加一个按钮。
  4. 执行与错误处理:调用main()函数,并用try...catch包裹进行错误处理。

一个典型的开发模式是:你在main()函数里,使用chatgpt.js提供的 API 来监听页面事件、查询DOM元素、插入你的自定义UI组件(如按钮、面板),并定义这些组件被点击或交互时要执行的操作(例如,调用api.sendMessage发送特定指令)。

4.2 启动开发服务器与热重载

这是本启动器最爽的功能之一。在项目根目录的终端中,运行:

npm run dev # 或 pnpm dev

这个命令会启动 Vite 开发服务器,并开始监听src/目录下的文件变化。同时,它会在dist文件夹中生成一个*.user.js文件(例如chatgpt.js-greasemonkey-starter.user.js)。

接下来,你需要做一件至关重要的事情:在浏览器中打开 ChatGPT 的网页,然后打开油猴插件(Tampermonkey)的管理面板,点击“添加新脚本”。不要从头写,而是点击“文件”菜单或类似选项,选择“从磁盘导入...”,然后导航到你项目下的dist目录,选择那个刚刚生成的.user.js文件并导入。

导入成功后,确保该脚本是启用状态。现在,刷新 ChatGPT 页面。你的脚本应该已经生效了(初始模板可能会添加一个不起眼的测试按钮)。

魔法时刻:现在,回到你的代码编辑器,修改src/main.ts文件,比如改变一个按钮的文字。保存文件后,你会立刻在终端看到 Vite 重新构建的提示。无需手动刷新浏览器,只需切回 ChatGPT 页面,稍等一秒(或者看到页面轻微闪动),你的修改就已经实时生效了!这个热重载功能极大地提升了开发调试效率。

4.3 编写你的第一个功能:添加一个“总结”按钮

假设我们想实现一个经典功能:在ChatGPT输入框旁添加一个“总结”按钮,点击后自动向ChatGPT发送“请总结上面的对话内容”的指令。

首先,我们需要了解chatgpt.js的一些基本API。查看其文档或类型提示,我们会找到与输入框和发送消息相关的方法。

src/main.tsmain()函数中,我们可以这样写:

import { ChatGPTAPI } from 'chatgpt.js'; async function main() { // 等待ChatGPT页面核心组件加载就绪 const api = new ChatGPTAPI(); await api.waitForReady(); // 获取聊天输入框的容器,通常我们可以在其附近添加按钮 const inputContainer = await api.getInputContainer(); if (!inputContainer) { console.warn('未找到输入框容器'); return; } // 创建我们的“总结”按钮 const summarizeButton = document.createElement('button'); summarizeButton.textContent = '📝 总结'; summarizeButton.style.marginLeft = '10px'; summarizeButton.style.padding = '8px 12px'; summarizeButton.style.borderRadius = '6px'; summarizeButton.style.border = '1px solid #ccc'; summarizeButton.style.background = '#f7f7f8'; summarizeButton.style.cursor = 'pointer'; // 为按钮添加点击事件 summarizeButton.addEventListener('click', async () => { // 在发送前,可以给用户一个反馈,比如禁用按钮或改变文字 summarizeButton.textContent = '总结中...'; summarizeButton.disabled = true; try { // 使用 chatgpt.js 的API发送一个预设的提示词 await api.sendMessage('请总结上面的对话内容。'); } catch (error) { console.error('发送总结请求失败:', error); // 可以在这里添加用户提示,例如一个Toast通知 } finally { // 无论成功失败,恢复按钮状态 summarizeButton.textContent = '📝 总结'; summarizeButton.disabled = false; } }); // 将按钮插入到输入框容器的后面(或其他你觉得合适的位置) inputContainer.parentNode?.insertBefore(summarizeButton, inputContainer.nextSibling); console.log('“总结”按钮已添加!'); } // 执行主函数,并捕获可能出现的错误 main().catch(console.error);

保存文件。由于开发服务器正在运行,你的改动会立刻生效。刷新ChatGPT页面,你应该能在输入框附近看到一个崭新的“总结”按钮。点击它,ChatGPT就会收到你的指令并开始工作。

实操心得:在插入自定义UI元素时,CSS样式管理是个小挑战。直接写内联样式(style.xxx)对于简单按钮可行,但组件复杂后会很乱。一个更好的实践是:在src/目录下创建一个style.css文件,编写你的样式,然后在main.ts中通过import './style.css';引入。Vite会自动处理CSS的打包和注入。这样代码更清晰,也便于维护。

5. 构建、发布与脚本管理

5.1 生产环境构建

当你完成了脚本功能的开发,并经过充分测试后,就需要构建一个用于分发的版本。运行:

npm run build # 或 pnpm build

这个命令会启动 Vite 的生产模式构建。它与开发模式 (dev) 的关键区别在于:

  • 代码压缩混淆:生成的.user.js文件会被最小化和混淆,减小体积,保护源代码逻辑。
  • 移除开发调试代码:一些仅在开发时使用的代码会被剔除。
  • 生成Source Map(可选):如果配置了,会生成.map文件,便于线上调试(但发布时通常不包含)。

构建完成后,最终的脚本文件同样位于dist/目录下。这个文件就是你可以分享给他人,或发布到 Greasy Fork、OpenUserJS 等脚本平台的成品。

5.2 脚本元信息与发布

油猴脚本文件头部有一段特殊的注释,称为“元数据块”,它定义了脚本的名称、版本、描述、匹配的网址、授权权限等。在这个启动器中,这部分信息主要由vite.config.ts中的GreasemonkeyPlugin配置来自动生成和管理。

关键的元信息通常在package.jsonvite.config.ts中定义。例如,脚本的@name,@version,@description通常会从package.json的对应字段读取。而@match(指定脚本在哪些网址上运行) 则在vite.config.ts的插件配置里设置。

发布前检查清单

  1. 更新版本号:在package.json中修改version字段。遵循语义化版本控制(如从1.0.01.0.1)。
  2. 检查匹配规则:在vite.config.ts中确认@match@include规则是否正确覆盖了你的目标网站(例如https://chat.openai.com/*)。
  3. 完善描述:更新package.json中的descriptionvite.config.ts中更详细的描述,让用户明白脚本的用途。
  4. 构建:运行pnpm build生成最终文件。
  5. 手动验证:用文本编辑器打开dist/下的.user.js文件,检查头部的元信息是否正确无误。
  6. 发布:将构建出的.user.js文件内容复制,到 Greasy Fork 等平台创建/更新你的脚本。

5.3 版本控制与协作

由于这是一个标准的 Node.js 项目,你可以完美地使用 Git 进行版本控制。将node_modulesdist目录添加到.gitignore中,只提交源代码和配置文件。这样,你的团队可以协作开发,清晰地跟踪每一次功能添加和Bug修复。

6. 进阶技巧与深度定制

6.1 利用chatgpt.js的全部能力

chatgpt.js库非常强大,远不止发送消息。深入其文档,你可以发现更多宝藏功能:

  • 对话历史管理api.getConversationHistory()可以获取当前会话的所有消息,用于本地分析或导出。
  • 监听事件:库可能提供了消息接收、发送完成等事件监听器,让你能在更精确的时机执行操作。
  • UI组件操作:除了输入框,还可以获取消息流容器、侧边栏等,用于创建更复杂的交互界面,比如一个常驻的侧边工具面板。

6.2 处理动态内容与页面导航

ChatGPT 是一个单页应用(SPA),在对话间切换或刷新时,URL可能不变,但DOM会更新。你的脚本需要能应对这种动态性。chatgpt.jswaitForReady()方法已经帮我们处理了初始加载。但对于后续的页面状态变化,你可能需要:

  • 使用 MutationObserver:监听特定DOM子树的变化,当检测到输入框区域重新渲染时,重新执行你的UI注入逻辑。
  • 合理设置脚本执行时机:油猴元数据中的@run-at可以设置为document-idle,确保页面基本加载完毕后再执行你的脚本。

6.3 与后端服务通信

如果你的脚本需要从外部API获取数据(例如,从你自己的服务器获取配置,或者将处理后的对话内容发送到笔记软件),你需要使用油猴提供的GM_xmlhttpRequestAPI。这个启动器已经自动处理了@grant GM_xmlhttpRequest的声明。你可以在代码中直接使用:

// 注意:这是一个示例,实际使用需要更完善的错误处理和类型定义 GM_xmlhttpRequest({ method: 'POST', url: 'https://your-api.com/endpoint', data: JSON.stringify({ content: '要发送的数据' }), headers: { 'Content-Type': 'application/json' }, onload: function(response) { console.log('API响应:', response.responseText); // 处理响应数据 }, onerror: function(error) { console.error('API请求失败:', error); } });

重要提示:由于跨域限制,普通网页脚本无法直接请求任意API。但油猴脚本通过GM_xmlhttpRequest拥有更高的权限,可以跨域请求。但这同时也带来了安全风险,请确保你请求的是可信的端点。

6.4 配置化与用户设置

一个成熟的脚本应该允许用户进行一些自定义配置。你可以:

  1. 使用GM_getValue/GM_setValue:油猴提供的存储API,适合保存简单的键值对配置(如开关状态、API密钥)。
  2. 创建配置面板:在脚本中注入一个设置图标,点击后弹出一个模态框(Modal),里面包含表单元素(输入框、下拉菜单、开关等),让用户进行配置。配置保存时,调用GM_setValue存储。
  3. 提供默认值:在脚本初始化时,用GM_getValue读取配置,如果没有则使用硬编码的默认值。

7. 常见问题排查与调试心得

即使有了强大的启动器,开发过程中仍会遇到各种问题。这里记录一些常见坑点和解决思路。

7.1 脚本未运行或按钮未出现

  • 检查油猴插件是否启用:确保Tampermonkey图标是彩色的,并且你的脚本处于“已启用”状态。
  • 检查匹配网址:确认脚本的@match规则包含了当前浏览的ChatGPT网址。有时https://chat.openai.com/*https://chat.openai.com/有细微差别。
  • 查看浏览器控制台:按 F12 打开开发者工具,切换到“控制台”标签页。查看是否有红色的报错信息。启动器生成的脚本会将其console.log输出到这里,这是最重要的调试信息源。常见的错误可能是chatgpt.js库未加载(检查网络),或你的代码有语法错误。
  • 检查脚本安装方式:开发时务必使用“从磁盘导入”的方式安装dist/下的脚本,而不是手动创建。确保你导入的是开发服务器生成的文件。

7.2 热重载失效

  • 确认开发服务器在运行:终端里pnpm dev的命令是否还在运行,且没有报错退出。
  • 检查油猴脚本更新:有时油猴插件不会自动检测磁盘文件的变更。你可以尝试在油猴插件的管理面板中,找到你的脚本,点击其旁边的“检查更新”按钮。
  • 手动刷新页面:如果热重载不生效,最直接的方式还是手动刷新浏览器页面。

7.3chatgpt.jsAPI 调用失败

  • 等待页面就绪:确保在调用任何操作DOM的API前,已经await api.waitForReady()。ChatGPT页面加载需要时间。
  • API 变更:ChatGPT的网页前端结构可能会更新,导致chatgpt.js的某些底层选择器失效。关注chatgpt.js库的更新日志,及时升级项目依赖 (pnpm update chatgpt.js)。
  • 错误处理:用try...catch包裹你的核心逻辑,并在catch块中给出友好的用户提示或记录详细的错误信息到控制台。

7.4 构建失败

  • TypeScript 类型错误:运行pnpm build前,可以先运行pnpm type-check(如果配置了)或tsc --noEmit来检查类型错误。
  • 依赖缺失:删除node_modulespackage-lock.json(或pnpm-lock.yaml),重新运行pnpm install
  • 检查配置文件:对比项目原始仓库的vite.config.ts,看是否有不小心改错的地方。

7.5 样式冲突或布局错乱

  • CSS 作用域:你注入的样式可能会影响网页原有样式,或被网页样式覆盖。尽量使用特定的类名,并增加CSS选择器的特异性。例如,为你创建的按钮添加一个独特的前缀类名.my-script-summarize-btn,然后所有样式都基于这个类名来写。
  • 使用 Shadow DOM(高级):为了彻底隔离样式,可以考虑将你的UI组件封装到一个Shadow DOM中。但这会带来事件处理的复杂性,需酌情使用。

开发浏览器脚本,尤其是针对复杂SPA的脚本,耐心和细致的调试是关键。充分利用浏览器开发者工具的“元素检查器”和“控制台”,它们是你最好的朋友。这个启动器提供的现代化工具链,已经将开发过程中的大量摩擦点消除了,让你能更专注于创造有价值的功能本身。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 8:02:36

大模型时代来临:小白程序员必学指南,收藏这份高效学习路线!

随着DeepSeek等大模型技术的兴起,AI岗位需求激增,程序员面临职业转型挑战。文章提供大模型应用开发的学习路线,分为基础、RAG应用开发工程、大模型Agent应用架构、微调与私有化部署四个阶段,帮助读者系统掌握大模型技术&#xff0…

作者头像 李华
网站建设 2026/5/15 8:02:29

【C++ 在线五子棋对战】 - 数据库用户表管理

一、模块概述 数据库模块负责用户数据的持久化存储,包括用户注册、登录验证、信息查询和战绩更新。本模块包含两个文件:文件功能说明db.sql数据库建表脚本 — 定义用户表结构db.hpp用户表操作类 — 封装所有数据库增删改查操作模块依赖关系: …

作者头像 李华
网站建设 2026/5/15 8:01:23

无损精准查缆:鼎讯 G-340A 在铁路高速场景的应用

铁路与高速沿线光缆密集敷设、环境复杂,人工识别目标光缆难度大、效率低,还易损伤在用线路。鼎讯 G-340A 光缆普查仪(敲缆仪)依托光纤弹光效应,以无损探测、智能便捷的优势,成为铁路高速光缆区分、故障排查…

作者头像 李华
网站建设 2026/5/15 8:01:20

基于Whisper与LLM的视频自动字幕生成与摘要项目实战

1. 项目概述:当AI遇见视频,自动生成字幕与摘要 最近在折腾一个挺有意思的项目,叫 vidscribe 。简单来说,这是一个利用人工智能技术,自动为视频生成字幕(SRT文件)和内容摘要的工具。如果你像我…

作者头像 李华
网站建设 2026/5/15 7:59:15

单元式幕墙分类及特点

单元式幕墙分类及特点 "单元式幕墙"主要可分为:"单元式幕墙"和"半单元式幕墙"又称坚挺单元式幕墙,半单元式幕墙详分又可分为:立挺分片单元组合式幕墙,窗间墙单元式幕墙。 上述单元式幕墙分类有所不同,但其基本原理完全一致。它和框架式幕…

作者头像 李华