从开发chrome插件到插件系统设计

简介: 最近ChatGPT的技术概念很火热,开发了一个node-gptcommit开源项目,主要利用GPT用来自动生成git commit的信息。

背景


最近ChatGPT的技术概念很火热,开发了一个node-gptcommit开源项目,主要利用GPT用来自动生成git commit的信息。


但是通过命令行工具来生成preview感觉有点不太友好,因此在想有没有另外一种可能将其变得更加好用,然后想到一个场景:

  • 在合mr的时候,以及代码review,很多git commit 文件,需要一一个看


在这个时刻,自动生成commit信息就显得很有用,因此有个想法就是将node-gptcommit做成chrome插件,然后帮助MR的开发者能够快速了解此次MR的所有内容。


当然仅仅是开发一个chrome插件大家上网随便搜一下就知道怎么开发,因此为了本文更加有干货,需要更加深入的知识,所以本文分为两部分:

  • Chrome插件开发,如何快速开发一个插件
  • Chrome插件架构设计,了解Chrome插件背后的架构设计,以及前端插件架构体系

Chrome插件开发


Chrome插件是一种浏览器扩展程序,可以增强浏览器的功能和用户体验。Chrome插件可以添加新的工具栏、菜单、快捷键、热键等,还可以修改网页的行为和外观,以及与网页交互,实现各种功能。常见的Chrome插件包括广告拦截器、翻译插件、下载管理器、音乐播放器等。


开发Chrome插件其实很简单,因为Chrome的插件主要描述文件mainfest.json,还有包含在里面的一些其他文件,具体如下:

  • manifest.json文件,用于指定插件的名称、版本号、描述等信息,以及指定插件的各种权限和资源
  • popup.html文件,主要用于显示插件的弹出窗口,提供用户界面和交互功能
  • content scripts文件,用于向网页注入JavaScript代码,从而实现与网页的交互。这些脚本可以访问网页的DOM和JavaScript对象,并且可以向网页发送消息和接收来自网页的消息。
  • background scripts文件,用于在Chrome插件的后台运行JavaScript代码,可以与popup、contentscript等通讯,可以实现发起网络请求、拦截用户访问请求等操作


一个标准的Chrome插件目录结构如下:

my-extension/
├── _locales/
│   ├── en/
│   │   └── messages.json
│   └── zh/
│       └── messages.json
├── css/
│   └── popup.css
├── img/
│   ├── icon128.png
│   ├── icon48.png
│   └── icon16.png
├── js/
│   ├── background.js
│   ├── content.js
│   └── popup.js
├── popup.html
├── manifest.json
└── README.md

其中,各个文件夹和文件的作用如下:

  • _locales/:存放插件的本地化文件,用于支持不同语言版本的插件。
  • css/:存放插件的CSS样式文件。
  • img/:存放插件的图标文件。
  • js/:存放插件的JavaScript文件,包括background scripts、content scripts和popup scripts等。
  • popup.html:插件的popup页面。
  • manifest.json:插件的配置文件,用于指定插件的名称、版本号、描述等信息,以及指定插件的各种权限和资源。
  • README.md:插件的说明文档,用于介绍插件的功能和使用方法等。

manifest.json


manifest.json是Chrome插件的配置文件,用于指定插件的名称、版本号、描述等信息,以及指定插件的各种权限和资源。

下面是一个完整的manifest.json文件的例子:

{
  "manifest_version": 2,
  "name": "My Chrome Extension",
  "version": "1.0",
  "description": "This is a description of my Chrome extension",
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },
  "background": {
    "scripts": ["background.js"]
  },
  "content_scripts": [
    {
      "matches": ["*://*.example.com/*"],
      "js": ["content.js"]
    }
  ],
  "permissions": [
    "tabs",
    "*://*.example.com/*"
  ]
}

其中:

  • manifest_version:指定manifest.json文件的版本号,一般为2
  • name:指定插件的名称
  • version:指定插件的版本号
  • description:指定插件的描述
  • icons:指定插件的图标,这里16、 48、128指的是需要展示在不同场景插件的图标
  • browser_action:可以配置的popup页面和图标
  • permissions:插件需要的权限,例如访问浏览器标签页,以及只允许在*://.example.com/域名才有效


还有两个相对复杂配置项:

  • content_scripts: content_scripts指定插件需要向*://.example.com/注入JavaScript代码,代码位于content.js文件中
  • background:指定插件的background.js文件为background scripts

popup.html


就是一个简单html文件,里面需要插件的UI展示,demo如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>My Chrome Extension</title>
  <link rel="stylesheet" href="popup.css">
  <script src="popup.js"></script>
</head>
<body>
  <h1>Hello, World!</h1>
  <p>This is my first Chrome extension.</p>
  <button id="myButton">Click me!</button>
</body>
</html>

popup.html文件可以包含任何HTML、CSS和JavaScript代码,用于构建插件的用户界面和交互功能。在上面的例子中,popup.html文件包含一个标题、一段文本和一个按钮,按钮的点击事件可以在popup.js文件中进行处理。需要注意的是,popup.html文件的UI通常比较简单,因为其主要作用是提供与用户的交互和反馈。


除了HTML、CSS和JavaScript代码外,popup.html文件还可以包含其他类型的资源文件,例如图片、音频或视频文件等。这些资源文件可以放置在相应的目录下,并在HTML代码中使用相应的路径引用。在实际开发中,可以根据需要对popup.html文件进行扩展和修改,以实现更复杂的用户界面和交互功能。

content_scripts


content_scripts你可以当成用户页面内的js,Content scripts常用于修改网页的行为和外观,以及与网页交互,实现各种功能。例如,可以通过content scripts实现自动填充表单、隐藏广告、添加自定义菜单等功能。下面是一个简单的content_scripts的例子,使得当用户进入Google搜索页面时,输入框默认输入“Hello World!”:

// manifest.json
{
  "name": "My Content Script",
  "version": "1.0",
  "manifest_version": 2,
  "content_scripts": [
    {
      "matches": ["<https://www.google.com/*>"],
      "js": ["content.js"]
    }
  ]
}
// content.js
document.querySelector('input[name="q"]').value = 'Hello World!';

在这个例子中,我们在manifest.json文件中指定了一个content_scripts,用于在用户进入https://www.google.com/*网页时自动向Google搜索框中输入“Hello World!”。具体实现的代码在content.js文件中,使用document.querySelector()函数获取到输入框,并将其value属性设置为“Hello World!”。


需要注意的是,content_scripts只能访问网页的DOM和JavaScript对象,并不能直接访问插件的资源和API。如果插件需要向网页发送消息或从网页接收消息,可以使用chrome.runtime.sendMessage()chrome.runtime.onMessage()等API实现。

backgroundjs


backgroundjs是运行在后台的一个js文件,里面可以实现各种监听,如:tab监听、插件初始化、sendmessage、onmessage等事件,下面我们来实现一个简单的发送网络请求:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.type === 'fetch') {
    fetch(request.url)
      .then(response => response.text())
      .then(data => sendResponse({ success: true, data }))
      .catch(error => sendResponse({ success: false, error }));
    return true;
  }
});

常用的监听事件有:

  • chrome.runtime.onMessage.addListener(), 监听插件传递过来的的消息事件
  • chrome.runtime.onInstalled.addListener(), 监听插件的安装事件
  • chrome.runtime.onStartup.addListener(), 监听插件的启动事件
  • chrome.tabs.onUpdated.addListener(), 监听浏览器标签页更新事件

当然对应的事件都需要在manifest.jsonpermissions去配置才能开启。

Chrome插件设计架构


既然弄明白了如何开发一个Chrome插件,那么作为一个合格的程序员,我们不仅要知道是什么,还要知道为什么,这才能让你不断地进步。


我们回头再来思考一下,插件有什么用,以及为什么要有插件?

插件最大的作用就是扩展主应用App的功能,同时支持可插拔特性,就是有没有插件,都不会影响现有主应用功能正常使用。

接下来我们来思考,如何我来开发一个chrome插件系统,我应该如何设计呢?下面是简易Chrome插件系统的架构图:

cfdcfe789deb5b848846f0074aa2102.png

有了上面的架构,我们可以大概知道实现一个插件系统需要几个功能点:

  • 插件管理,需要有插件上传、加载、版本机制等功能
  • 暴露能力,需要确定暴露哪些API能力,同时还需要展示插件的UI
  • 隔离环境,需要确保插件的隔离性,不影响主应用的运行,这里就需要我们去用iframe的模式去执行

插件系统设计


有了对chrome的插件架构有一定了解后,如果这个时候需要我们需要对某个平台去实现一个插件系统,我们应当如何入手以及设计?


在做插件系统之前,我们需要再明确一下插件的定义:

插件是平台核心功能的一种扩展,是在平台生命周期流程中的不同节点去扩展或调整功能

接下来,我们按照几个步骤去实现插件:

插件系统的定位


我们的插件肯定依附于某个平台或应用上的,因此我们需要先对平台能力做一个定位,就以Chrome为例子,chrome浏览器作为展示网页为核心功能。

那么如果去设计一个插件系统,肯定是围绕着网页展示的扩展功能去做插件系统设计。

插件系统的基础能力


插件系统的基础能力包括以下几点:

  • 插件管理,需要插件管理界面,面对开发者:,提供上传、版本管理等功能,面对使用者:需要提供安装、查询、删除等功能
  • 插件开发,需要给开发者提供工具、文档、规范、发布流程等方便的信息

插件系统架构设计


针对不同平台,可能需要插件架构是不一样的,如:Chrome,采用的并行机制,不同插件可以在同一时间加载、输出。


前端领域很多有插件实现架构,按照执行顺序可以大概分为如下几种:

插件架构 描述 适⽤场景 框架或应用
顺序执行 显然就是从头执行到尾,不断对内容做修改 ⼤多数场景 babel plugin
瀑布流 上一层输出就是下一层输入,这里就是管道概念 管道 Gulp
洋葱 不仅关注输入,而且关心输出,还可以随时直接输出 进出 Koa
并发执⾏ 多个输入,对多个插件输出做一个总结输出 ⽆序任务 webpack complier

(参考自前端早早聊 2023年前端插件设计专场 【洋葱:插件化设计在前端领域的应用】)


同时,从架构上还需要考虑以下几点:

  • 插件接口,指的是哪些平台哪些接口Hook,允许插件访问或改变
  • 插件管理器,指的平台如何管理插件,包括更新、审核、插件的文件模式等。
  • 插件加载器,指的平台如何加载插件,是在加载过程需要如何塞入暴露能力等。
  • 插件生命周期,指的是一个插件有哪些生命周期节点,如:安装、加载、运行、卸载、禁用等

插件系统的安全和稳定性


我们不仅要考虑插件功能实现,还需要考虑插件的安全和稳定性,主要从以下几方面入手:

  • 插件的安全验证,指的是如何限制非法插件的使用
  • 插件的权限控制,指的是如何限制插件的权限
  • 插件的资源隔离,指的是如何确保插件其运行环境不可以访问平台其他非暴露资源

总结


经过本文,我们不仅学会了Chrome插件的开发,还对插件系统的设计有一定的认知,我们回顾一下:

  • Chrome插件开发,主要组成部分为:manifest.json,popup.html,content_scripts和background.js
  • 插件系统设计,主要考虑的点:管理、开发工具和文档、暴露能力、安全与稳定

参考资料


目录
相关文章
|
11天前
|
Web App开发 前端开发 JavaScript
手摸手教你,从0到1开发一个Chrome浏览器插件
开发 Chrome 插件既有趣又具成就感。本教程将引导你从零开始,逐步创建一个简单的 Chrome 插件。首先了解 Chrome 插件是可增强浏览器功能的小程序。以一个基础示例开始,你将学习如何设置开发环境,包括安装 Chrome 和准备文本编辑器,并掌握 HTML、CSS 和 JavaScript 的基础知识。接着,我们将构建插件的基本结构,涉及 `manifest.json` 配置文件、`background.js` 后台脚本、`popup.html` 用户界面以及 `style.css` 样式表。
57 8
|
5天前
|
Web App开发
Chrome 护眼模式 - 黑暗模式 - 夜眼(Night Eye) 插件
Chrome 护眼模式 - 黑暗模式 - 夜眼(Night Eye) 插件
13 0
Chrome 护眼模式 - 黑暗模式 - 夜眼(Night Eye) 插件
|
24天前
|
Web App开发 前端开发 Java
通过设置 Chrome 解决开发调用跨域问题
通过设置 Chrome 解决开发调用跨域问题
139 7
|
29天前
|
Web App开发 JavaScript 前端开发
Chrome插件实现问题之最新的 Chrome 浏览器架构有什么新的改变吗
Chrome插件实现问题之最新的 Chrome 浏览器架构有什么新的改变吗
|
29天前
|
JavaScript 前端开发 Web App开发
Chrome插件实现问题之单进程浏览器的不稳定主要体现在什么地方
Chrome插件实现问题之单进程浏览器的不稳定主要体现在什么地方
|
29天前
|
Web App开发 数据可视化 前端开发
Chrome插件实现问题之content-scripts能访问哪些Chrome API
Chrome插件实现问题之content-scripts能访问哪些Chrome API
|
29天前
|
Web App开发 前端开发 JavaScript
Chrome插件实现问题之用户在浏览器中输入URL后,浏览器进程会进行什么操作
Chrome插件实现问题之用户在浏览器中输入URL后,浏览器进程会进行什么操作
|
29天前
|
Web App开发 JavaScript 前端开发
Chrome插件实现问题之在Manifest V2中,设置插件的图标要如何解决
Chrome插件实现问题之在Manifest V2中,设置插件的图标要如何解决
|
29天前
|
缓存 安全 Web App开发
Chrome插件实现问题之网络进程接收到URL请求后会如何解决
Chrome插件实现问题之网络进程接收到URL请求后会如何解决
|
29天前
|
Web App开发 存储 JavaScript
Chrome插件实现问题之Manifest V2切换MV3会带来什么问题,如何解决
Chrome插件实现问题之Manifest V2切换MV3会带来什么问题,如何解决

热门文章

最新文章