注册
web

TabFlow: 一款简洁的 Chrome 标签页域名分类器

TabFlow:打造智能化的Chrome标签页管理扩展


前言


在日常的Web开发和浏览过程中,我们经常会同时打开大量的标签页。当标签页数量超过10个时,浏览器的标签栏就会变得拥挤不堪,找到特定的页面变得困难。为了解决这个痛点,我开发了TabFlow——一个智能的Chrome标签页分组管理扩展。


项目概述


TabFlow是一个基于Chrome Extension Manifest V3的标签页管理工具,它能够:



  • 🏷️ 智能分组:自动按域名对标签页进行分组
  • 🎨 视觉区分:为不同域名分配独特的颜色标识
  • 📊 实时统计:显示标签页数量和域名统计
  • 性能优化:采用防抖、缓存等技术确保流畅体验

截屏2025-09-28 23.15.21.png


技术架构


1. 项目结构


TabFlow/
├── manifest.json # 扩展配置文件
├── background.js # 后台服务脚本
├── popup.html # 弹窗界面
├── popup.js # 弹窗逻辑
└── icons/ # 图标资源
├── icon16.png
├── icon48.png
└── icon128.png

2. 核心技术栈



  • Chrome Extensions API:标签页和分组管理
  • Manifest V3:最新的扩展开发标准
  • Service Worker:后台处理逻辑
  • Modern CSS:毛玻璃效果和渐变设计

核心功能实现


1. 智能域名解析


首先,我们需要从URL中提取有意义的域名信息:


function parseUrl(url) {
if (domainCache.has(url)) {
return domainCache.get(url);
}

try {
const urlObj = new URL(url);
let hostname = urlObj.hostname;

// 移除www前缀
if (hostname.startsWith('www.')) {
hostname = hostname.substring(4);
}

// 提取主域名
const parts = hostname.split('.');
let mainDomain = hostname;

if (parts.length >= 2) {
const commonTLDs = ['com', 'org', 'net', 'edu', 'gov', 'cn', 'jp', 'uk'];
const lastPart = parts[parts.length - 1];

if (commonTLDs.includes(lastPart)) {
mainDomain = parts.slice(-2).join('.');
} else {
mainDomain = parts.slice(-3).join('.');
}
}

const displayName = mainDomain.split('.')[0].toUpperCase();
const result = { mainDomain, displayName };

// 缓存结果,限制缓存大小
if (domainCache.size > 100) {
const firstKey = domainCache.keys().next().value;
domainCache.delete(firstKey);
}
domainCache.set(url, result);

return result;
} catch (e) {
return null;
}
}

技术亮点



  • 使用Map缓存解析结果,避免重复计算
  • 智能处理各种TLD(顶级域名)
  • 限制缓存大小防止内存泄漏

2. 自动分组机制


当检测到同域名的多个标签页时,自动创建或更新分组:


async function autoGr0upTabsByDomain(mainDomain, displayName, tabs, color) {
try {
// 使用缓存的分组信息
let existingGr0ups;
if (groupCache.has('groups')) {
existingGr0ups = groupCache.get('groups');
} else {
existingGr0ups = await chrome.tabGr0ups.query({});
groupCache.set('groups', existingGr0ups);
setTimeout(() => groupCache.delete('groups'), 5000);
}

const targetGr0up = existingGr0ups.find(group =>
group.title.includes(displayName)
);

if (targetGr0up) {
// 添加到现有分组
const ungroupedTabs = tabs.filter(tab => tab.groupId === -1);
if (ungroupedTabs.length > 0) {
const tabIds = ungroupedTabs.map(tab => tab.id);
await chrome.tabs.group({ tabIds, groupId: targetGr0up.id });

// 获取分组中的实际标签页数量
const groupTabs = await chrome.tabs.query({ groupId: targetGr0up.id });
await chrome.tabGr0ups.update(targetGr0up.id, {
title: `${displayName} (${groupTabs.length})`
});
}
} else if (tabs.length > 1) {
// 创建新分组
const tabIds = tabs.map(tab => tab.id);
const groupId = await chrome.tabs.group({ tabIds });

await chrome.tabGr0ups.update(groupId, {
title: `${displayName} (${tabs.length})`,
color: GR0UP_COLORS[color] || 'grey',
collapsed: false
});
}

groupCache.delete('groups');
} catch (e) {
console.log('分组失败:', e);
}
}

截屏2025-09-28 23.17.15.png


3. 实时数量更新


这是项目中的一个技术难点。Chrome的标签页分组API在标签页数量变化时不会自动更新分组标题,需要我们主动监听和更新:


// 监听标签页移除,更新分组标题
chrome.tabs.onRemoved.addListener(async (tabId, removeInfo) => {
try {
const groups = await chrome.tabGr0ups.query({});

for (const group of groups) {
const groupTabs = await chrome.tabs.query({ groupId: group.id });
if (groupTabs.length > 0) {
const titleMatch = group.title.match(/^(.+?)\s*\(/);
if (titleMatch) {
const displayName = titleMatch[1];
await chrome.tabGr0ups.update(group.id, {
title: `${displayName} (${groupTabs.length})`
});
}
}
}
} catch (e) {
console.log('更新分组标题失败:', e);
}
});

// 定期更新分组标题(每5秒检查一次)
async function updateAllGr0upTitles() {
try {
const groups = await chrome.tabGr0ups.query({});

for (const group of groups) {
const groupTabs = await chrome.tabs.query({ groupId: group.id });

const titleMatch = group.title.match(/^(.+?)\s*\(/);
if (titleMatch && groupTabs.length > 0) {
const displayName = titleMatch[1];
const currentTitle = `${displayName} (${groupTabs.length})`;

if (group.title !== currentTitle) {
await chrome.tabGr0ups.update(group.id, {
title: currentTitle
});
}
}
}
} catch (e) {
console.log('更新分组标题失败:', e);
}
}

setInterval(updateAllGr0upTitles, 5000);

技术亮点



  • 多重监听机制确保数量实时更新
  • 正则表达式解析分组标题
  • 定时器作为兜底方案

4. 现代化UI设计


采用了Apple设计语言,实现了毛玻璃效果和流畅的动画:


.container {
padding: 20px;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}

.stats {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
padding: 16px 20px;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20px);
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
}

.domain-item {
display: flex;
align-items: center;
padding: 14px 16px;
margin-bottom: 10px;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(20px);
border-radius: 12px;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.domain-item:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
}

截屏2025-09-28 23.18.18.png


性能优化策略


1. 缓存机制


let domainCache = new Map();     // 缓存域名解析结果
let groupCache = new Map(); // 缓存分组信息
let pendingUpdates = new Set(); // 防止重复处理

2. 防抖处理


let updateTimeout;
function debounceTabUpdate(callback, delay = 500) {
clearTimeout(updateTimeout);
updateTimeout = setTimeout(callback, delay);
}

3. 批量操作


// 并行处理分组
const groupPromises = Object.entries(domainGr0ups)
.filter(([, domainTabs]) => domainTabs.length > 1)
.map(async ([mainDomain, domainTabs]) => {
const urlInfo = parseUrl(domainTabs[0].url);
if (urlInfo) {
const color = assignColorToDomain(mainDomain);
return autoGr0upTabsByDomain(mainDomain, urlInfo.displayName, domainTabs, color);
}
});

await Promise.all(groupPromises);

图标设计


为了让扩展更具视觉吸引力,我设计了一套现代化的图标:


icon128.png


图标采用了:



  • 蓝紫色到粉色的渐变背景
  • 多层标签页卡片效果
  • 流动箭头指示分组功能
  • 现代化的扁平设计风格

开发过程中的挑战与解决方案


1. Manifest V3迁移


Chrome Extensions从V2迁移到V3带来了一些挑战:


问题:Background Scripts改为Service Worker
解决:重构代码结构,使用事件驱动模式


// Manifest V3配置
{
"manifest_version": 3,
"background": {
"service_worker": "background.js",
"type": "module"
},
"permissions": [
"tabs",
"storage",
"tabGr0ups"
]
}

2. 分组标题实时更新


问题:Chrome API不会自动更新分组标题中的数量
解决:实现多重监听机制 + 定时同步


3. 性能优化


问题:频繁的API调用导致性能问题
解决:引入缓存、防抖、批量处理等优化策略


安装TabFlow后,用户可以:



  1. 自动按域名分组标签页
  2. 通过颜色快速识别不同网站
  3. 实时查看每个分组的标签页数量
  4. 一键整理所有标签页

技术总结


通过开发TabFlow,我深入学习了:



  1. Chrome Extensions API:掌握了标签页、分组、存储等核心API
  2. 性能优化:学会了缓存、防抖、批量处理等优化技术
  3. 现代CSS:实践了毛玻璃效果、渐变、动画等现代设计
  4. 用户体验:理解了如何设计直观易用的界面

项目地址



未来规划



  1. 智能分组算法:基于用户习惯的智能分组
  2. 标签页搜索:快速搜索和定位标签页
  3. 数据同步:跨设备同步分组配置
  4. 快捷键支持:键盘快捷键操作

结语


TabFlow不仅解决了我个人的标签页管理痛点,也是一次完整的Chrome扩展开发实践。从需求分析到技术实现,从性能优化到用户体验,每一个环节都充满了学习和挑战。


希望这个项目能够帮助更多开发者提高浏览效率,也欢迎大家提出建议和贡献代码!




如果你觉得这篇文章对你有帮助,欢迎点赞和分享。如果你有任何问题或建议,也欢迎在评论区讨论!


作者:用户40738558808
来源:juejin.cn/post/7554979158435643407

0 个评论

要回复文章请先登录注册