javascript-Chrome扩展入门

Chrome扩展入门

Chrome扩展能为Chrome浏览器增加新的功能和特性,为用户提供定制化的浏览体验,如果有一些自己需要的功能,也可以尝试自己写一些扩展来实现。开发Chrome扩展所需要的技术和WEB前端开发并无不同,都是需要

  1. HTML
  2. CSS
  3. JavaScript

本质上来时,Chrome扩展就是工作在客户端浏览器上的JavaScript程序。如果说写Chrome扩展有什么需要新学的东西,那就是Chrome浏览器的Javascript APIs,通过浏览器的API,我们可以

  1. 修改Chrome浏览器原有的功能和行为;
  2. 允许用户收集和组织(重新组织)网上的信息;
  3. 给Chrome的DevTools添加新的特性。

正是Google提供的扩展开发功能,为Chrome浏览器带来了源源不断的创新动力。

目前Chrome建议使用的是Manifest V3,本文以此为环境写作。

扩展的设计原则

Chrome的扩展设计要求遵循“单一目的”原则,该原则包含两个方面:

  1. 扩展的主题或关注领域集中,例如“新闻头条”,“天气”,“购物比价”。千万不要像国内很多软件那样做得那么大而全。
  2. 扩展的功能集中,例如“标签管理”,“搜索功能”,“新标签页面”。

扩展的文件结构

扩展根据所需的功能,包含的文件千差万别,其中最常用的如下。

  1. (必需)manifest文件。此文件翻译为“清单文件”,是唯一必需的文件,且名字必须为manifest.json(显然是个json文件),放在扩展的根目录文件夹下。Chrome浏览器通过该文件找到扩展配置并载入,manifest.json中记录了扩展重要的元信息、定义资源、声明权限同时指定哪些文件在后台运行,哪些在前台显示,可以说是扩展的指导手册。
  2. service worker。通常是Javascript文件,监听并处理浏览器事件,例如跳转到新的页面、删除书签、关闭标签(tabs)等等。service worker可以使用所有的Chrome APIs,但是不能直接和页面的内容进行交互,那是Content scripts的工作。service worker一般运行在后台。
  3. content scripts。一般也是Javascript文件,content scripts在页面上下文中执行Javascript脚本,能够读取和修改DOM节点,并向指定页面注入JS和CSS。content scripts只能直接使用部分Chrome APIs,不过,如果需要的话,可以与service worker交互来间接地使用其余的Chrome APIs。
  4. UI元素。扩展的页面部分也是由HTML文件组成,包括图标、popup页面,配置页面等等,这些页面并不是必需的,开发者可以按需添加,这些页面也可以使用Chrome APIs。

一般常用目录结构如下:

 1|-- my-extension/
 2    |-- manifest.json // 清单文件。必需
 3    |-- background.js // service worker文件,后台
 4    |-- scripts/
 5    |      ﹂ content.js // 前端内容处理
 6    |      ﹂ others.js // 其他库,支持文件,按需命名
 7    |-- popup/  //扩展按钮
 8    |      ﹂ popup.html
 9    |      ﹂ popup.js
10    |      ﹂ popup.css
11    ﹂ images/ //所需图片
12           ﹂ icon-16.png // 各种尺寸的图标
13           ﹂ icon-32.png
14           ﹂ icon-48.png
15           ﹂ icon-128.png

需要指出的是,上述文件结构除了manifest.json文件的名字和位置固定,其他文件的名字和位置都可以通过manifet.json中进行指定和配置,文件中的路径都使用相对路径

入门例子:Hello World Extension

在了解了Chrome扩展大体结构后,我们用一个简单的“Hello”例子来展示下扩展的简要开发流程。这个“Hello”扩展的效果是当我们点击工具栏上的扩展图标,就会弹出“Hello Extensions 我的第一个扩展”。

第一步,我们需要在跟目录建立一个manifest.json文件。manifest.json内容可以分为三类,Required,Recommended和Optional。

  • Required: 必需的,3个
    • "manifest_version":当前版本为3,现在推荐就写3。
    • "name":开发者定义的扩展名称。
    • "version":开发者扩展的版本。
  • Recommended:推荐要有的,4个
    • "action":使用chrome.action接口控制Chrome工具栏的扩展动作。工具栏的扩展图标是一定存在的,无论是否有可用的操作。
    • "default_locale":默认语言环境,在有本地化的扩展中是必需的(带_locales文件夹),如果没有_locales文件夹,则一定不要写。
    • "description":扩展的简要描述。
    • "icons":{...}。扩展的图标,总是要求提供128*128的图标,同时最好提供48*48的图标(用于管理页)和16*16的图标。为了保证通用性,最好用png格式。实际上,即使没有图标,Chome也会给弄个默认的。
  • Optional:可选的,剩余的都是。常用的有:
    • "author":开发者名称
    • "background":{...}设置"service_worker"的条目;
    • "content_script":[{...}]设置"content script"脚本;
    • "permissions":["..."]允许的权限;
    • "short_name":扩展的简称(短名);
    • "update_url": Chrome商店以外的更新地址,在国内很有用;
    • "version_name":扩展版本的名称。

根据上面的介绍,我们可以写出"hello"扩展的manifest.json文件。需要指出的是,json文件在JSON5标准之前都不支持注释,因此在真正使用时,需要将注释内容去除。

 1{
 2//Required
 3"manifest_version": 3,
 4"name": "Hello Extensions",
 5"version": "1.0", //注意这里是字符,不是数字
 6//Recommended
 7"action":{
 8    "default_popup": "hello.html",//点击工具栏扩展图标后显示的弹窗
 9    "default_icon": "hello_extensions.png"//默认图标地址
10    },
11// "default_locale" 没有本地化文件,一定不要写
12"description": "My first new extension.",
13//"icon"先不写,看看Chrome给的默认的长什么样
14//Optional
15"author": "SurprisedCat"
16}

第二步,根据manifest.json中的配置,我们在根目录下创建hello_extensions.png图片(图片大家可以根据自己喜好选一个)和hello.html文件,该文件就是点击工具栏扩展图片后显示的页面文件,代码如下:

1<html>
2  <meta charset="utf-8"> 
3  <body>
4    <h1>Hello Extensions</h1>
5    <h2>我的第一个扩展</h2>
6  </body>
7</html>

现在我们的文件结构如下:

1﹂- hello/
2    |-- manifest.json
3    |-- hello_extensions.png
4    ﹂- hello.html

保存好现有的3个文件,我们先来尝试本地载入扩展看看效果。

第三步,载入未打包的扩展。

  1. 在浏览器URL中输入chrome://extensions打开扩展设置页面。
  2. 打开页面右上角的“开发者模式”。
  3. 点击页面左上角的“加载已解压的扩展程序”,并在找到刚刚存放三个文件的hello文件夹。

chrome_extension_hello_load

这样我们就载入了自己编写的第一个扩展!我们点击工具栏就可以发现自己编写的扩展已经运行了,单击"hello"扩展,就弹出了hello.html中设置的内容。效果如下:

hello extensions

当我们对manifest.json中的内容进行修改后,比如将其中的名称项"name": "Hello Extensions of the world!",换个名字,还需要重新载入扩展,点击下图圆圈箭头按钮。

chrome_extension_hello_reload

可以发现扩展名称已经被修改了。不过,并不是所有的修改都需要重新载入扩展,下表显示了哪些文件修改后需要重载扩展。

扩展组成部件 是否需要重载
The manifest
Service worker
Content Scripts 是 (包括原页面)
The popup
Options page
Other extension HTML pages

调试扩展

在开发期时,我们一般可以通过两种方式调试代码,一种是自己在代码中添加console.log()提示错误,另一种使用Chrome的开发者工具来调试。

我们还用上面"hello extension"的例子,简要介绍两种方式的使用。首先,我们对hello.html进行修改如下:

1<html>
2  <meta charset="utf-8"> 
3  <body>
4    <h1>Hello Extensions</h1>
5    <h2>我的第一个扩展</h2>
6    <script src="popup.js"></script> <!--引入一个新的js文件-->
7  </body>
8</html>

引入的popup.js文件同样放在根目录下:

1console.log("This is a popup!")

保存文件后,重载扩展。

第一个,使用console.log()。现在的问题就是哪里能到看它的输出结果。我们右键点击工具栏的"hello"扩展,在菜单中点击“审查弹出内容”。在弹出的开发者工具中,选择“console”控制面板,就可以看console.log()输出的内容了。

chrome_extension_debug_consolelog

第二个,如果我们的扩展出现了一些无法运行的错误,就无法使用console.log调试了,我们可以借助Chrome开发者工具的错误信息,比如在popup.js中,我们出现了语法错误,少打了一个引号:

1console.log("This is a popup!) // ❌ broken code

当我们重新载入扩展时,会发现扩展页面多了一个“错误”按钮,点击后出现:

chrome_extension_debug_error.png

这样就能够根据提示调试代码。注意,这里的错误信息是不会自动删除的,即使后面改对了,之前的错误信息也会保留下来,必需自行手动清除。

此外,在开发者工具中,也会有错误代码位置的提示。

关于扩展(extensions),插件(plugins)与应用(Apps)

在Chrome浏览器的发展中,扩展(extensions),插件(plugins)与应用(Apps)三个词都曾出现过。

不过现在Chrome目前不再提插件这种讲法,而广大用户也常常把插件和扩展当成一回事。严格来讲,扩展是利用浏览器已有的API,进行二次开发,提供新功能,新特性的代码,开发者只是将浏览器已潜在具备但尚未提供的功能组合出来。插件则是由于浏览器本身缺乏相应功能,使用底层内核API开发的新功能,例如过去Chrome不支持Flash,因此有Flash插件。从开发者角度来看,插件的开发难度是远大于扩展的。从用户角度看,二者都是提供了新功能,因此常常认为两者差不多。随着Google公司在互联网领域的话语权逐步增强和Chrome浏览器的逐渐完善,目前我们可以说Chrome已经不缺重要的功能,因此插件这个东西就逐渐不需要了。现在更多的是根据用户自身需求所定制化的扩展,目前用户所说的Chrome浏览器插件,实际上都是指Chrome的扩展,或者连在一起称为Chrome扩展插件。Chrome商店里提供的也都是Chrome扩展。

而Chrome应用(App)则是Google竞争失败的产物。2010年左右,Google公司提出了一个非常有魄力的想法,将Chrome浏览器做成一个像操作系统一样的大平台(实际上Google确实做到了),其他应用都跑在Chrome这个平台上,就是Chrome Apps。但是,用户们显然对这个想法不买账,而且随着网络前端能力的增强,Chrome应用变得很鸡肋。于是在2016 年,Google宣布会逐渐抛弃Chrome App,进一步拥抱网页平台。最终2022年6月,谷歌所有客户终止了Chrome App的支持。Chrome App已经陷入历史的尘埃中。

最终,只有轻量级的Chrome扩展留存下来,并且得到了越来越多用户的喜爱。后来,微软的IE和后续的Edge都被Chrome打的溃不成军,不得已放弃了自己的浏览器内核,在2018年采用了Chromium的Blink内核,这使得Chrome扩展也能够运行在Edge浏览器上,可以说是Chrome扩展的高光时刻了。至于以后,微软会不会反水,再弄一个自己的内核分庭抗礼,让我们拭目以待。

参考文档

  1. Google官方文档https://developer.chrome.com/docs/extensions/mv3/