# 深入了解Chrome插件

An image

# 简介

Chrome 插件可以做很多事情,比如做json格式化的JSON Formatter (opens new window),将json在web端的可读性提升了N个级别;又或者前端工程师们,经常需要在页面上copy文字,可能需要这个Auto Clipboard (opens new window)插件,只要选中文本,自动复制到剪切板。一个优质的插件,可以大大提示学习和开发效率。

Chrome插件入门级的教程网上已经有很多了,这里就不再赘述,需要注意的是,网上大部分教程都是基于Manifest V2的,目前最新的Manifest版本是V3,并且,2022年1月中旬,Chrome不再接受Manifest V2插件的发布,所以建议没有接触过Chrome插件的同学,先参考Google官方最新的入门级插件Chrome Extensions samples (opens new window)了解一下,再往下看。

# 组成Chrome插件的基本元素

一个Chrome插件的基本元素包括后台脚本(background.js)、内容脚本(content_scripts.js)、配置页面(options page)、弹窗页面(popup page)以及清单(manifest.json)

它们的作用如下:

  • 后台脚本(background.js)运行在后台的js文件,通常用来监听事件,注意:后台脚本不能访问DOM
  • 内容脚本(content_scripts.js),注入到已加载的浏览器页面上下文中执行的js文件,如果页面包含iframe,内容脚本会在每个iframe内嵌页面上下文中执行
  • 配置页面(options page),顾名思义,用来做插件的个性化配置的页面,配置可以保存到chrome.storage,类似于localStorage,chrome.storage分为chrome.storage.local和chrome.storage.sync,chrome.storage.sync会自动同步到用户登录的任何Chrome浏览器,chrome.storage.local只会保存到本地
  • 弹窗页面(popup page)用户点击Chrome右上角的插件图标时,弹出的页面
  • 清单(manifest.json)用来配置插件的版本、权限以及后台脚本、内容脚本、配置页面、弹出页面等,所有的配置请查看官方开发者文档Manifest file format (opens new window)

# 各元素之间的关系

Chrome插件基本元素可以单独运作,但相互协作才能体现出它的价值。

清单除了可以用来做插件的配置,还可以使用“commands”定义一些键盘快捷键,在后台脚本使用chrome.commands.onCommand.addListener监听快捷键的触发

内容脚本、配置页面、弹出页面三者与后端脚本的通信,通过chrome.runtime.sendMessage发送信息,后端脚本使用chrome.runtime.onMessage.addListener监听

An image

# 如何解决插件热更新问题?

热更新在前端开发领域是个标准配置,但是到了Chrome插件开发,会发现插件不会随着代码的热更新而重新加载。查阅Chrome插件开发者文档,发现有个chrome.runtime.reload,是用来重新加载插件的,可以解决这个问题。

回顾前面所讲,可以配置一个快捷键,一键刷新插件

在manifest.json 增加如下配置

"commands": {
  "reload_extension": {
    "suggested_key": {
      "default": "Ctrl+Shift+K",
      "mac": "Command+Shift+K"
    },
    "description": "重新加载插件"
  }
}

接着在后台脚本监听快捷键

chrome.commands.onCommand.addListener((command)=>{
  if(command === 'reload_extension'){
    chrome.runtime.reload();
  }
});

配置完成后,代码更新后只需要按下快捷键,即可刷新插件。当然,更好的做法是,将这个刷新插件的功能单独做成一个插件,因为这跟插件的业务功能没有关系,只是开发需要,不应该和业务代码放在一起。

# 配置页面和弹出页面可以做成多页面吗?

可以。配置页面和弹出页面有各自的入口文件,可以分别做成单页应用,使用前端路由切换多页面。

# 如何在页面里插入自定义页面?

某些场景下,需要在第三方页面上插入自己的自定义页面,有很多种方法

  • 用原生js创建DOM元素和样式插入到页面,优点是没有第三方依赖,缺点是效率低,样式没有隔离
  • 使用web component创建自定义元素,优点是样式、事件隔离,缺点是chrome插件不支持,chrome插件里的window是简化版的,window.customElements值是undefined,无法创建自定义元素
  • 将自定义页面作为配置页面或弹出页面内某个子页面,利用iframe加载,chrome.runtime.getURL可以获取指定页面src,然后赋值给iframe即可。优点是可以和插件本身的页面共用一套技术栈,并且可以利用chrome.runtime.sendMessage和插件通讯,样式和事件也是隔离的,没有明显的缺点,推荐这种方式

# chrome.runtime.sendMessage和chrome.tabs.sendMessage

两者都是用来向扩展中的事件监听器发送消息的,不同的是,chrome.tabs.sendMessage是向指定tab发送消息,chrome.runtime.sendMessage是向所有tab发送,并且,要向内容脚本发送消息,只能使用chrome.tabs.sendMessage

上次更新: 11/19/2021, 11:36:00 AM