1. 项目背景与痛点解析
作为一名长期奋战在一线的前端工程师,我最近完成了一个解决实际开发痛点的谷歌插件项目。这个项目的起源要追溯到我们团队长期被CAS登录流程折磨的经历——每次本地开发时,都需要手动将登录成功的token添加到localhost地址的localStorage中,测试同学切换账号时更是需要反复退出、重新登录。这些看似微小的操作,在日积月累下变成了巨大的时间黑洞。
1.1 CAS登录的痛点细节
在我们的系统中,CAS登录流程存在几个关键问题点:
-
开发阶段:每次启动本地服务,都需要先通过浏览器正常登录系统,然后手动从开发者工具中复制token,再粘贴到localhost的localStorage中。这个过程不仅繁琐,而且容易出错。
-
测试阶段:测试同学需要频繁切换不同权限的账号进行测试。每次切换都需要:
- 手动退出当前账号
- 清除浏览器缓存
- 重新输入另一账号的凭据登录
- 重复开发阶段的token复制粘贴流程
-
技术实现:系统使用axios的响应拦截器进行token验证,如果检测不到合法token,就会重定向到CAS登录页。这意味着我们需要在页面加载的最早期就注入token。
提示:这种登录流程的低效性在需要频繁环境切换的前后端分离项目中尤为明显,特别是当后端API强制要求CAS认证时。
1.2 解决方案的核心思路
基于这些痛点,我确定了解决方案的几个关键点:
-
自动化token获取:通过插件自动完成从登录页面提取token的过程,避免手动复制粘贴。
-
早期脚本注入:在页面加载的最初阶段就将token注入到localStorage,确保axios拦截器能检测到有效token。
-
多账号管理:提供便捷的账号切换功能,避免重复登录操作。
这个方案看似简单,但在实现过程中需要考虑诸多细节,比如注入时机、跨域问题、token刷新机制等。下面我将详细介绍如何用最高效的方式实现这个工具。
2. 技术选型与开发环境搭建
2.1 为什么选择谷歌插件?
在评估多种解决方案后,我最终选择了开发谷歌插件,主要基于以下考虑:
-
直接操作浏览器环境:插件可以访问和修改页面的DOM、拦截请求、操作localStorage等,完美契合我们的需求。
-
开发成本低:相比于开发独立应用,插件开发更轻量,可以快速迭代。
-
部署方便:团队成员只需安装插件即可使用,无需额外配置。
-
跨平台性:Chrome插件在Edge等基于Chromium的浏览器上也能运行。
2.2 开发工具链配置
为了实现极致性价比的开发,我精心挑选了以下工具组合:
2.2.1 编辑器选择
-
TraeCN Free版:
- 满足80%的基础开发需求
- 对TypeScript支持良好
- 轻量快速,适合日常编码
-
QCoder Pro版($10-20/月):
- 作为TraeCN的补充,处理复杂场景
- 提供更强大的代码补全和错误检查
- 特别适合解决疑难问题
注意:这两个编辑器的组合使用很有讲究。我的经验是先用TraeCN尝试解决问题,只有当遇到3次以上prompt无法解决的难题时,才切换到QCoder。这样可以最大化性价比。
2.2.2 辅助工具
-
Chrome Dev Tools:用于调试插件和观察token注入效果。
-
File System API:管理插件本地存储的配置数据。
-
GitHub:版本控制和代码托管。
2.3 项目初始化
-
创建标准的Chrome插件项目结构:
code复制/src /background - 后台脚本 /content - 内容脚本 /popup - 弹出窗口UI manifest.json - 插件配置文件 package.json - 项目依赖 -
配置manifest.json:
json复制{ "manifest_version": 3, "name": "Peaks Login Helper", "version": "1.0", "permissions": [ "storage", "activeTab", "scripting" ], "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"] } ] } -
安装TypeScript和相关类型定义:
bash复制
npm install -D typescript @types/chrome
3. 核心功能实现细节
3.1 Token自动获取与注入机制
这是整个插件的核心功能,实现起来需要解决几个关键问题:
3.1.1 监听登录成功
我们通过内容脚本(content script)监听登录页面的变化,检测登录成功的标志:
typescript复制// content.js
const observeLoginSuccess = () => {
const targetNode = document.getElementById('login-status');
const config = { attributes: true, childList: true, subtree: true };
const callback: MutationCallback = (mutations) => {
for (const mutation of mutations) {
if (mutation.target.textContent?.includes('登录成功')) {
extractAndStoreToken();
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
};
3.1.2 Token提取与存储
从登录成功后的页面提取token并存储到插件的本地存储中:
typescript复制const extractAndStoreToken = () => {
const token = localStorage.getItem('auth_token');
if (token) {
chrome.storage.local.set({ 'peaks_token': token }, () => {
console.log('Token stored successfully');
});
}
};
3.1.3 早期脚本注入
通过动态创建script标签的方式,在页面加载的最早期注入token:
typescript复制const injectTokenScript = (tabId: number) => {
chrome.scripting.executeScript({
target: { tabId },
func: (token) => {
localStorage.setItem('auth_token', token);
},
args: [token],
world: 'MAIN' // 在主世界执行,而非隔离的内容脚本环境
});
};
重要提示:必须使用
scripting.executeScript并在MAIN世界执行,这样才能确保token在axios拦截器生效前就已经存在于localStorage中。
3.2 多账号管理系统
为了方便测试同学切换不同账号,我们实现了账号管理系统:
3.2.1 账号存储结构
typescript复制interface AccountProfile {
username: string;
token: string;
lastUsed: number;
permissions: string[];
}
const storeAccount = (account: AccountProfile) => {
chrome.storage.local.get(['peaks_accounts'], (result) => {
const accounts = result.peaks_accounts || [];
accounts.push(account);
chrome.storage.local.set({ 'peaks_accounts': accounts });
});
};
3.2.2 快速切换实现
typescript复制const switchAccount = (accountId: string) => {
chrome.storage.local.get(['peaks_accounts'], (result) => {
const account = result.peaks_accounts.find(acc => acc.username === accountId);
if (account) {
injectTokenScript(account.token);
chrome.tabs.reload(); // 刷新页面使新token生效
}
});
};
3.3 请求拦截与错误处理
为了处理token过期等情况,我们实现了请求拦截和自动刷新机制:
typescript复制chrome.webRequest.onBeforeSendHeaders.addListener(
(details) => {
// 从localStorage获取当前token
const token = localStorage.getItem('auth_token');
// 添加到请求头
details.requestHeaders?.push({
name: 'Authorization',
value: `Bearer ${token}`
});
return { requestHeaders: details.requestHeaders };
},
{ urls: ['<all_urls>'] },
['blocking', 'requestHeaders']
);
4. 开发过程中的经验与教训
4.1 Vibe Coding实践心得
采用Vibe Coding(无Review开发模式)有几点关键体会:
-
文档先行:在开始编码前,先用markdown写出完整的产品文档,明确每个功能的输入输出和行为边界。这能大幅减少后期返工。
-
小步快跑:将功能拆分为最小可验证单元,逐个实现和测试。比如先实现token提取,再实现注入,最后做UI集成。
-
自动化测试:虽然不进行代码Review,但必须为关键路径编写测试脚本。我们使用Jest进行单元测试:
typescript复制describe('token injection', () => { it('should inject token before page load', () => { // 测试代码 }); });
4.2 编辑器使用技巧
-
TraeCN的高效用法:
- 利用代码片段功能保存常用模板
- 配置项目特定的lint规则
- 对复杂类型使用TypeScript的"快速修复"功能
-
QCoder的进阶技巧:
- 极致模式下可以处理复杂类型推导
- 利用其强大的重构能力整理代码结构
- 对性能关键代码进行深度分析
4.3 常见问题排查
-
Token注入失败:
- 检查manifest中的权限配置
- 确认scripting.executeScript在正确的时机调用
- 验证注入的脚本是否在MAIN世界执行
-
跨域问题:
json复制// manifest.json "host_permissions": [ "*://*.yourdomain.com/*" ] -
存储同步问题:
- 使用chrome.storage.sync代替local实现多设备同步
- 添加存储变更监听器
typescript复制chrome.storage.onChanged.addListener((changes) => { // 处理存储变化 });
5. 项目成果与后续优化
5.1 效率提升数据
使用该插件后,团队效率得到显著提升:
- 开发人员配置环境时间从平均5分钟/次降至10秒/次
- 测试人员账号切换时间从2分钟/次降至5秒/次
- 因token错误导致的调试时间减少约80%
5.2 开源与社区反馈
项目已在GitHub开源,收到了一些有价值的反馈:
- 有用户建议增加token自动刷新功能
- 需要支持更多类型的认证方式(如OAuth2.0)
- 对多标签页场景的更好支持
5.3 未来优化方向
-
可视化配置界面:让非技术人员也能方便地管理账号和token。
-
Token自动刷新:在token临近过期时自动获取新token。
-
环境配置预设:保存不同环境的配置,一键切换开发/测试/生产环境。
-
性能监控:记录插件自身的性能指标,确保不会对页面加载造成明显影响。
这个项目从构思到上线仅用了2人天,却解决了团队长期存在的痛点问题。它再次证明:好的工具不在于技术有多复杂,而在于能否精准解决实际问题。如果你也面临类似的CAS登录效率问题,欢迎试用我们的开源插件并提出改进建议。