首页 > 其他分享 >从0到1设计开发Chrome插件

从0到1设计开发Chrome插件

时间:2024-02-20 13:25:24浏览次数:29  
标签:插件 const Chrome tbody chrome 设计 链接

TNTWeb - 全称腾讯新闻中台前端团队,组内小伙伴在Web前端、NodeJS开发、UI设计、移动APP等大前端领域都有所实践和积累。

目前团队主要支持腾讯新闻各业务的前端开发,业务开发之余也积累沉淀了一些前端基础设施,赋能业务提效和产品创新。

团队倡导开源共建,拥有各种技术大牛,团队Github地址:https://github.com/tnfe

本文作者冷叶 项目地址: https://github.com/freezeYe/wukong-chrome-plugin

image.png

一、场景

之前一直在公司业务上做H5开发,发现项目的繁琐点不在某一个具体的业务逻辑,而是无数个已经上线或者下线亦或是反反复复上上下下的AB测。对于前端开发来说,其中一个低效的点便在于如何去管理众多的链接,因为每一个参数对应了一个命中实验。举个 ,首先是域名我们有四套(本地、测试、预发布、线上)环境,然后是页面路径总共有两级页每一级对应了无数个文章链接,而每个文章链接又对应了多个AB测参数。
Chrome上自带了书签功能,但一个问题是书签只能做单链接存储,在实际开发中我们的域名、路径和参数其实都拥有自身的含义,比如

https://view.kuaikan.com/a2/20171129V077ODs0?W2VIDEO=1&pluginab=1&tint=1&W2VIDEOLAB=0

这样的一个链接,他表达了怎样的实际意义呢?如下图所示:

其实这是一个排列组合的问题,我们期望的是可以在链接的每个维度上做拆分,并通过灵活重组生成新的链接并快捷访问。在这个基础上就引入了本文要介绍的“悟空记录”插件,这样我们就可以在最大程度上复用单个链接的每个字段。

wecom-temp-0eaa1ff42eddeff9091392fea68766a3.png

二、悟空记录

在Chrome网上商店搜索“悟空插件”点击“添加至Chrome”,我们就可以在浏览器右上角看到这样的icon标签
这就是我们的悟空插件应用。

插件核心分为三部分,第一部分是保存页。在下图我们能看到顶部显示了当前活动tab的url链接,下面三个输入框分别对应了我们对该链接域名、路径、参数的独立定义,填写上对应的值后点击保存我们会看到输出结果。

wecom-temp-fd3e19478f7eb42cf610ab39ae0d6727.png

第二部分是访问列表页,点击“访问”我们能看到之前已经保存的原信息,这里我又单独添加了一条线上环境的域名记录,所有链接的重复字段值采用了复写机制。

wecom-temp-4d188a2f16777fe3dba498487ac2c813.png

在上图中点选择任意组合,点击打开后我们就可以看到新的重组链接被打开了。

image.png
第三部分是信息管理页面,我们点击弹出页中的“扩展程序选项”,就能看到先前记录的所有信息。目前只支持了删除功能,后续计划在页面上提供组合链接直接生成二维码能力来优化移动端开发体验。

image.png

三、Chrome插件开发

深入了解插件开发前先我们先来理清一些基本的概念。首先是background.js 定义了插件注册安装到浏览器时自动执行的一些操作,比如根据当前环境来判断该插件是否启用(icon高亮/置灰)。popup.html就是我们在点击插件时的弹窗,popup.js是拥有其执行上下问的脚本文件。contentscript.js 注入了我们打开一个网页时的context,它与前述的脚本环境隔离,通过postMessage的形式来互相通信。下图少了一部分options.html和options.js,这是选项页面和他自身的执行脚本,在插件开发中一般用来做独立的管理后台,在下文介绍本插件的开发中会描述到。

wecom-temp-7d0f25594bdaf05bb2f7a6c82e1b7820.png

有了这些概念后我们会想,chrome是如何去识别每个内容呢?它其实是通过manifest.json的json文件,里面描述了对应的资源路径,以悟空插件来看。

name:当我们鼠标放到插件icon上显示的组件名;
version:发布到chrome插件商店对应版本号;
description:显示在插件上的简短介绍;
browser_action:指定了浏览器安装插件后显示的icon和点击时弹出的页面;
icons:显示在商城、设置等地方所对应的不同尺寸icon;
options_page:指定了我们的选项页;
permissions:指定了对该插件的chrome api授权,为了防止xss等诸如攻击。
这里我们缺少的其余两个重要选项是background,因为该插件不存在需要后台运行的js,还有一个是page_action对应了browser_action,区别在于browser_action作用于所有页面,通过page_action配置的popup.html需要手动调用chrome的api激活。

{
  "name": "Domain and Parameter combination",
  "version": "1.0",
  "manifest_version": 2,
  "author": "freezeYe",
  "description": "Separate Domains and Parameters and Regroup",
  "permissions": ["storage", "declarativeContent", "activeTab", "tabs"],
  "browser_action": {
    "default_popup": "src/html/popup.html",
    "default_icon": "images/nokia_suite_mirror.png"
  },
  "icons": {
    "16": "images/nokia_suite_mirror.png",
    "32": "images/nokia_suite_mirror.png",
    "48": "images/nokia_suite_mirror.png",
    "128": "images/nokia_suite_mirror.png"
  },
  "options_page": "src/html/options.html"
}

接下来在对应路径下创建相应的文件,我们就能通过扩展程序的“加载已解压的扩展程序”来将项目打包到我们自身的浏览器上来同步开发。

image.png

开发框架可以按照个人喜好配置,只要保证最终打包成浏览器兼容的JS即可。这里放一段该项目选项页的原生JS代码,由于项目比较小巧并没有再使用其他的库和框架,仅供参考。

const hostContainer = document.getElementById('host');
const pathContainer = document.getElementById('path');
const queryContainer = document.getElementById('query');

// storage 缓存键
const CACHED_KEY = '__wukongCache';
function init() {
  chrome.storage.sync.get([CACHED_KEY], (result) => {
    const { __wukongCache = {} } = result;
    const { hostMap, pathMap, queryMap } = __wukongCache;
    blockGen(hostMap, hostContainer, 'hostMap');
    blockGen(pathMap, pathContainer, 'pathMap');
    blockGen(queryMap, queryContainer, 'queryMap');
  });
}

// 根据数据生成对应区块
function blockGen(data, container, type) {
  let tbody = '';
  let thead = '<thead><tr><th>名称</th><th>值</th><th>操作</th></tr></thead>';
  Object.keys(data).forEach((key) => {
    tbody += `<tr>
      <td>${data[key]}</td>
      <td>${key}</td>
      <td class="delete" data-key=${key} >删除</td>
    </tr>`;
  });
  tbody = `<tbody>${tbody}</tbody>`;
  tbody = str2cell(tbody);
  thead = str2cell(thead);
  tbody.addEventListener('click', (e) => {
    if (e.target.innerText === '删除') {
      const r = confirm('确认删除该条记录?');
      if (r) deleteItem(e, type);
    }
  });
  // eslint-disable-next-line no-param-reassign
  container.innerHTML = '';
  container.append(thead);
  container.append(tbody);
}

// 字符串转dom
function str2cell(str) {
  const table = document.createElement('table');
  table.innerHTML = str;
  return table.firstChild;
}

// 删除元素
function deleteItem(e, type) {
  const { target } = e;
  const deleteKey = target.dataset.key;
  chrome.storage.sync.get(['__wukongCache'], (result) => {
    const { __wukongCache = {} } = result;
    const { [type]: data } = __wukongCache;
    Reflect.deleteProperty(data, deleteKey);
    chrome.storage.sync.set({ [CACHED_KEY]: __wukongCache }, init);
  });
}

init();

如何发布,当项目开发完成后打开Chrome网上应用商店,点击开发者信息中心按钮跳转。

新用户需要注册成为开发者,绑定信用卡/借记卡支付5美金。

image.png

注册成功后在首页点击“上传新内容”,将项目以manifest.json作为根路径的文件夹打包成.zip文件上传,最后在“商品详情”和“隐私权”等地方完善插件信息,直到“提交审核”按钮可点击后上传。

image.png

审核提交后我们就能在内容栏内看到我们的插件状态,当审核成功后我们就可以在Chrome商城内检索到我们的插件按照到浏览器啦,5美刀买不了吃亏买不了上当。

image.png

标签:插件,const,Chrome,tbody,chrome,设计,链接
From: https://www.cnblogs.com/tntweb/p/18022876

相关文章

  • 测试用例设计方法总结
    https://www.bilibili.com/video/BV1L54y1L7en/?spm_id_from=333.337.search-card.all.click&vd_source=773e87775bd767edb625b7665f58e881一、等价类划分法1.适用范围单个输入的功能2.定义具有代表性数据的子集3.分类有效等价类和无效等价类4.设计测试用例的步骤......
  • Babel 插件种类
    Babel插件种类:语法插件(SyntaxPlugins):语法插件负责扩展Babel的解析器,使其能够理解和解析新的或实验性的JavaScript语法特性。它们并不直接对代码进行转换,只是开启对应语法的解析功能。这意味着,如果没有相应的语法插件,Babel将无法正确解析某些新的或实验性的JavaScri......
  • 设计模式浅析(五) ·单例模式
    设计模式浅析(五)·单例模式日常叨逼叨java设计模式浅析,如果觉得对你有帮助,记得一键三连,谢谢各位观众老爷......
  • 程序设计天梯赛个人题解 L2-047-2 锦标赛
    题目分析综合题意,将最后一场比赛视为顶层,第一轮比赛视为第一层,则有:下层每场比赛选出一个胜者,每两个下层的胜者间举行本层的一次比赛,显然这是一个二叉树。考虑还原建立每场比赛的树。由于最后一层的比赛是$2^k$个选手参加,故这是个完美二叉树,使用完全二叉树的数组储存方式,则标号......
  • 磐维2.0 之pg_stat_statements插件
    目录一、概念描述二、安装插件三、pg_stat_statements视图四、pg_stat_statements相关参数五、测试验证一、概念描述pg_stat_statements是pg的一个扩展插件,通常用于统计数据库的资源开销,分析TOPSQL,找出慢查询。二、安装插件testdb=#testdb=#createextensionpg_stat_sta......
  • postman也不行!IDEA接口调试插件
    Postman是大家最常用的API调试工具,那么有没有一种方法可以不用手动写入接口到Postman,即可进行接口调试操作?今天给大家推荐一款IDEA插件:ApipostHelper,写完代码就可以调试接口并一键生成接口文档!而且还可以根据已有的方法帮助您快速生成url和params。更重要的是他完全免费!Apipos......
  • 设计模式之美学习-一些反思
    系统的看完各个设计模式,和开闭原则,实际中其实往往想不到如何使用比如业务场景,通过redis来模拟延迟消息处理还是采用传统思维模式写入消息//离线列表延迟一分钟redisOperationService.zaddWithPrefix(BusinessRedisKeyDefinition.SESSION_STATE_OFFLINE_QUEUE......
  • 旁门左道:借助 HttpClientHandler 拦截请求,体验 Semantic Kernel 插件
    前天尝试通过one-api+dashscope(阿里云灵积)+qwen(通义千问)运行SemanticKernel插件(Plugin),结果尝试失败,详见前天的博文。今天换一种方式尝试,选择了一个旁门左道走走看,看能不能在不使用大模型的情况下让SemanticKernel插件运行起来,这个旁门左道就是从StephenToub那......
  • 最新Burp Suite插件详解
    Burp Suite中的插件BurpSuite中存在多个插件,通过这些插件可以更方便地进行安全测试。插件可以在“BAppStore”(“Extender”→“BAppStore”)中安装,如图3-46所示。   图3-46   下面列举一些常见的BurpSuite插件。 1.Active Scan++ActiveScan++在BurpSuite......
  • PDF.js插件使用
    使用范围:在支持js的服务器上运行,适合电脑端(手机端没尝试过),使用方便使用方法:下载:https://mozilla.github.io/pdf.js/getting_started/ 解压后如下,将这些文件放到public里面或在public里建立一个自定义名称,如pdfjs的文件夹再放,我这边是直接放入 预览使用:http://localho......