关于 chrome 扩展的文章,很久之前也写过一篇。清除页面广告?身为前端,自己做一款简易的chrome扩展吧

本篇文章重在分享一些制作扩展的过程中比较重要的知识及难点。

什么是 chrome 扩展程序

扩展程序是一些能够修改或增强 Chrome 浏览器功能的小程序。对于前端工程师而言,其最大的便利就是我们可以应用我们熟悉的 HTML、CSS 、 Javascript 等技术来制作扩展程序。

如下图所示,这些图标就是各种开发者提供的 chrome 扩展程序:

区分扩展与插件

很多人会误称扩展程序为插件,这里有必要区分一下。

"扩展" 和 "插件",其实都是软件组件的一种形式,Chrome 只不过是把两种类型的组件分别给与了专有名称,一个叫 "扩展",另一个叫 "插件"。

  • 扩展(Extension)

指的是通过调用 Chrome 提供的 Chrome API 来扩展浏览器功能的一种组件,工作在浏览器层面,使用 HTML + Javascript 语言开发。比如著名的 Adblock plus。

  • 插件(Plug-in)

指的是通过调用 Webkit 内核 NPAPI 来扩展内核功能的一种组件,工作在内核层面,理论上可以用任何一种生成本地二进制程序的语言开发,比如 C/C++、Delphi 等。比如 Flash player 插件,就属于这种类型。一般在网页中用 <object> 或者 <embed>标签声明的部分,就要靠插件来渲染。

开发自己的扩展程序

OK,简单了解完什么是扩展程序后,下面我们来看看如何开发一款扩展程序。

当然,首先我们要搞清楚为什么我们需要扩展程序,它有什么作用呢?

就我而言,最近我开发了一款简单的扩展程序 —— URLHelper 。你可以在 chrome 应用商店下载到它:

开发它的原因是因为,在我们的业务开发中,开发过程经常需要面对超长的 URL,带有 N 多个参数,它可能长这样:

http://tv.video.qq.com/xxx/xxx/xxx/index?rootdomain=test.tv.video.qq.com&guid=066de07bdd33422f95b7ddaf993b2004&tvid=0930DCE900E081E142ED006B56025BA7&appver=3.1.0&bid=31001&appid=101161688&vipbid=38&fromvipbid=38&cid=qk97pyegxz8kdug&vid=&pid=&mid=&from=501&qua_info=PT%3DSNMAPP%26CHID%3D10009%26VN%3D3.1.0%26PR%3DVIDEO%26TVKPlatform%3D670603%26SMARKET%3D&type=0&listid=&matchid=&channelid=&source1=747&source2=709&penid=D21D81E4489E43422F842235B52DD&access=82E8E64DDD4A531B6FFA3E0967F76&kt_login=qq&vuserid=&vusession=&oauth_consumer_key=101161688&kt_userid=924400965&kt_license_account=SNM_0059858531&main_login=qq&kt_login_support=qq%2Cwx%2Cph&kt_boss_channel=tx_snm&ott_flag=2&sop=9&actid=&tvactid=&tv_params=policy_id%3D88&disable_update=&dp=&du=&viewid=&dv=&pageid=&ptag=&redirect_url=http%3A%2F%2Ftest.tv.video.qq.com%2Fktweb%2Fpay%2Fphone%2Fscan%3Frootdomain%3Dtest.tv.video.qq.com%26guid%3D066de07bdd33422f95b7ddaf993b2004%26tvid%3D0930DCE900E081E142ED006B56025BA7%26appver%3D3.1.0%26bid%3D31001%26appid%3D101161688%26vipbid%3D38%26fromvipbid%3D38%26cid%3Dqk97pyegxz8kdug%26vid%3D%26pid%3D%26mid%3D%26from%3D501%26qua_info%3DPT%253DSNMAPP%2526CHID%253D10009%2526VN%253D3.1.0%2526PR%253DVIDEO%2526TVKPlatform%253D670603%2526SMARKET%253D%26type%3D0%26listid%3D%26matchid%3D%26channelid%3D%26source1%3D747%26source2%3D709%26openid%3DD21D81E44801E9E43422F842235B52DD%26access_token%3D82E8E64DDD4EDA531B6FFA3E09676F76%26kt_login%3Dqq%26vuserid%3D%26vusession%3D%26oauth_consumer_key%3D101161688%26kt_userid%3D924400965%26kt_license_account%3DSNM_0059858531%26main_login%3Dqq%26kt_login_support%3Dqq%252Cwx%252Cph%26kt_boss_channel%3Dtx_snm%26ott_flag%3D2%26sop%3D9%26actid%3D%26tvactid%3D%26tv_params%3Dpolicy_id%253D88%26disable_update%3D%26dp%3D%26du%3D%26viewid%3D%26dv%3D%26pageid%3D%26ptag%3D%26opres%3D0&%24from=201

不是开玩笑,真实情况可能比这个还长。

因为调试的需要,经常要找到某一个特定的参数,获取或者修改它的值。

读者可以尝试一下,贴到浏览器中,找到 cid 参数,修改为另外一个值。如果没有工具,这个过程是很痛苦的。一次还好,如果一天重复这个动作几十次,就有必要考虑借助工具了。

基于这个出发点,我制作了 URLHelper 这个扩展,它的界面大概长这个样子,可以非常方便的对 URL 参数进行删查改排序,修改参数刷新页面:

所以,扩展程序我觉得每个前端都可以开发,用于解决我们工作生活中在使用浏览器遇到的各种问题,譬如有名的 :

  • WEB 前端助手 提供的字符串编码、JSON 格式化
  • PageSpeed 提供的页面性能检测等等
  • 二维码生成器 将 URL 转化成对应的二维码

扩展程序架构

OK,接下来聊聊一些扩展程序开发相关的东西。

关于扩展程序的相关文档,可以看看这些文章:

首先,我觉得最重要的,是要了解整个扩展程序的基本架构,有几个非常重要的文件:

Content scripts -- 内容脚本

Content scripts 脚本是指能够在浏览器已经加载的页面内部运行的 javascript 脚本。可以将 content script 看作是网页的一部分,而不是它所在的扩展程序的一部分。

它可以实现的一些功能的例子及适用场景,大致如下:

  • 在网页中找出未链接的 URL,并将它们转换为超链接
  • 查找特定的信息或者 DOM 结构,增加字体大小,使文本更具有可读性
  • 发现并处理 DOM 中的微格式数据

我们可以这样理解它,在页面加载完毕之后,我们的扩展程序会向这个页面注入一个或者额多个脚本,这个脚本可以获得浏览器所访问的 web 页面的详细信息。也就是我们可以利用这个脚本收集页面上各种我们需要的信息。

以我上面的 URLHelper 为例子,在这个扩展中,content script 的作用就是拿到页面的 URL ,然后传递给扩展程序的 background 页面或者 popup 页面。

当然,如果你只需要一个脚本程序每次注入页面后获取页面相关的信息,然后上报到自己的服务器之类的功能,这个扩展程序只需要这一个 Content scripts 就够了。它不需要与其他界面或者脚本进行交互和信息传递,扩展帮你做的就是自动注入这个脚本而需要你每次手动注入。

popup -- 弹窗页面

popup 页面也非常好理解,在 manifest.json 的定义里它是 browser_action, 就是我们扩展程序的界面(弹窗页),就是上面的那张截图:

这个界面其实就是一个 Web 页面,点开任意一个扩展页面,右键都可以看到弹出检查选项,点击这个选项,就会弹出一个开发者工具,我们就可以愉快的开始对这个页面进行查看 DOM 结构、查看网络状态、 Debug 等任意操作了:

然后:

重点,这个 popup 页面完全由我们控制,就像一个普通的 Web 页面,我们可以利用 Chrome 的消息传递机制利用这个页面和 Content scripts 进行交互,也就可以完成对页面的某些控制。以我上面的 URLHelper 为例子,在这个扩展中,当我点击扩展程序界面中的刷新页面按钮的时候,会从扩展界面的 DOM 上将修改后参数取出拼好,并且通过 Chrome 的消息传递机制 传递给 Content scripts,然

后 Content scripts 拿到新的参数,赋值给当前浏览器窗口页面的 document.location.href,实现页面的刷新。

background -- 后台网页

除了 popup 页面之外,还有一个 background 后台网页 。

chrome扩展程序将后台网页分为两种类型:

  • 持续运行的后台网页
  • 事件页面

是否持久存在是事件页面与后台网页之间的根本区别。(刚开始使用的时候可以理解为一个东西)

应用和扩展程序通常需要长时间运行的脚本来管理某些任务或状态,这就是后台页面的作用。事件页面只在需要时加载,当事件页面不活动时就会卸载,以便释放内存和其他系统资源,所以一般而言是推荐使用事件页面。

它存在的目的在于,在扩展的整个生命周期内需要长时间管理一些任务或状态。它的主要功能及适用场景,大致如下:

  • 事件页面监听的某个事件触发
  • 应用或扩展程序第一次安装或者更新到新版本(为了注册事件)
  • 内容脚本或其他扩展程序发送消息
  • 扩展程序中的其他视图调用了 runtime.getBackgroundPage

以我上面的 URLHelper 为例子,在这个扩展中,我使用的是持续运行的后台网页,当浏览器页面刷新第一次注入 Content Script 时,会获取到当前页面 url ,然后发送消息并带上 url 信息告诉给 background 后台网页, background 后台网页收到消息后,再转发给 popup 页面。

扩展程序小结

一个扩展程序最重要的我觉得就是上述的三块内容:

  • Content scripts -- 内容脚本
  • popup -- 弹窗页面
  • background -- 后台网页

我们通过一个 manifest.json 的清单文件来配置它们及一些额外信息。关于 manifest.json 的详细信息,可以戳:manifest 。

接下来,我们的扩展要灵活地完成各种功能,最重要的就是互相间的通信!

信息数据在内容脚本、弹窗页面以及事件页面之间传递是一个扩展程序最重要的部分。

扩展程序的消息传递

消息传递存在的必要性是因为内容脚本在网页而不是扩展程序的环境中运行,所以它们通常需要某种方式与扩展程序的其余部分通信。

扩展程序(弹窗页面和后台页面)和内容脚本间的通信使用消息传递的方式。两边均可以监听另一边发来的消息,并通过同样的通道回应。消息可以包含任何有效的 JSON 对象。

使用 chrome.* API

消息传递,主要使用了 Chrome 浏览器的内置 chrome 对象进行。打开浏览器,试一下,chrome 对象其实包含了非常多的功能:

各种类型的消息传递都是通过这个 chrome 对象进行,分为:

  • 简单的一次性请求
  • 长时间的连接
  • 跨扩展程序消息传递
  • 从网页发送消息
  • 原生消息通信

当然,对于通常而言的普通扩展程序而言,简单的一次性请求就足够我们使用了,举两个例子。

假设我们的 manifest.json 简单定义如下:

# manifest.json
{
"name": "Url Helper",
"version": "1.0.0",
"author": "Coco",
"manifest_version": 2, "browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"js": ["contentScript.js"]
}
]
}

从 Content Script 向 background 事件页面 传递消息

  • Content Script ,即是注入页面的脚本
# contentScript.js

// 发送消息
chrome.runtime.sendMessage(
{
msg: '从 Content Script 向 事件页面 传递消息',
result: 1
},
function(response) {
if (response && response.msg) {
console.log(response.msg);
}
}
);
  • background 后台页面
#background.js

// 接收消息
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.result) {
sendResponse({
farewell: "ok"
});
}
});

在发送端,我们可以使用 runtime.sendMessage 或 tabs.sendMessage 方法。这些方法分别允许您从内容脚本向扩展程序或者反过来发送可通过 JSON 序列化的消息,可选的 callback 参数允许您在需要的时候从另一边处理回应。

而在接收端,我们需要设置一个 runtime.onMessage 事件监听器来处理消息。

从 popup 弹窗页面 向 Content Script 传递消息

再举一个翻过来的例子,从 popup 弹窗页面 向 Content Script 传递消息。

  • popup 弹窗页面
# popup.html 页面内引入的 popup.js

let obj = {
msg: '从 popup 弹窗页面 向 Content Script 传递消息',
result: 0
}; // 发送消息
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, obj, function(response) {
console.log("Send Success");
});
});
  • Content Script
# contentScript.js

// 接收消息
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(sender.tab ? "来自内容脚本:" + sender.tab.url : "来自扩展程序"); if (request && !request.result) {
console.log(result.msg);
}
});

这里有个问题需要注意,从 popup 弹窗页面 向 Content Script 传递消息时,由于浏览器可能同时打开多个 tab 页,所以需要指定一下传递的页面,指定发送至哪一个标签页。

使用 chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {}) 则能正确选中当前打开的标签页。

其他更多的消息传递方式,可以戳这里:消息传递

将扩展程序打包上线发布到 Chrome 应用商店

扩展程序开发好了,希望供他人下载。那么当然需要发布到应用商店。流程大致如下:

登录到 Chrome 开发者信息中心。

首先,你需要有一个 Google 帐号,点击这里,登录网上应用商店

添加一个新项并以 zip 文件的形式上传文件。

成功之后,将会登录到这个界面,: 

在这个界面我们选择添加新内容即可 : 

注意,要打包成 *.zip 格式,并且在根目录下有最重要的 manifest.json 文件,像我上传的整个目录结构,就非常简单:

首次发布,需要支付 5 美刀

选择文件并且成功上传之后,下一步非常重要。第一次发布扩展程序,谷歌会收取 $5 开发者注册费用,之后可以发布 20 个扩展程序 。


这里付款中国内地的银行卡好像都不行,只能选择国外的 VISA 等储蓄卡、信用卡进行支付,地区选择美国即可。(寻找身边有 VISA 卡的小伙伴帮忙支付即可)

付款完成,可以愉快的发布了

OK,最后付款完成,就可以顺利发布了,稍等片刻,就可以搜索到我们自己开发扩展程序了!

仅供开发使用

当然,有些同学无法访问谷歌商店,或者扩展程序做出来仅仅是团队内部的一种工具,供私人使用。那么可以直接在 chrome 浏览器安装安装包。

  • 在 chrome 浏览器中访问 chrome://extensions(或者单击多功能框最右边的按钮:打开 Chrome 浏览器菜单,并选择更多工具 (L) 菜单下的扩展程序 (E),进入相同的页面)。
  • 确保右上角开发者模式复选框已选中,单击加载已解压的扩展程序 …,弹出文件选择对话框。
  • 浏览至您的扩展程序文件所在的目录,并选定。

扩展目录即是一个项目下的所有文件,开发调试时同理安装即可。

后记

其实开发一款 Chrome 扩展程序真的不难,而且非常有意思。感兴趣但又怕麻烦的同学可以参考我这个小项目改改。Github -- URL Helper

好了,本文到此结束,希望对你有帮助 :)

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

【前端工具】Chrome 扩展程序的开发与发布 -- 手把手教你开发扩展程序的更多相关文章

  1. ----转载----【前端工具】Chrome 扩展程序的开发与发布 -- 手把手教你开发扩展程序

    关于 chrome 扩展的文章,很久之前也写过一篇.清除页面广告?身为前端,自己做一款简易的chrome扩展吧. 本篇文章重在分享一些制作扩展的过程中比较重要的知识及难点. 什么是 chrome 扩展 ...

  2. 手把手教你开发chrome扩展

    转载:http://www.cnblogs.com/walkingp/archive/2011/04/04/2003875.html 手把手教你开发chrome扩展一:开发Chrome Extenst ...

  3. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单   手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...

  4. 手把手教你开发Chrome扩展三:关于本地存储数据

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 HTML5 ...

  5. 手把手教你开发Chrome扩展二:为html添加行为

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 上一节我们 ...

  6. 新书上线:《Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统》,欢迎大家买回去垫椅子垫桌脚

    新书上线 大家好,笔者的新书<Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统>已上线,此书内容充实.材质优良,乃家中必备垫桌脚 ...

  7. 最香远程开发解决方案!手把手教你配置VS Code远程开发工具,工作效率提升N倍

    文章每周持续更新,原创不易,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 今天和大家分享远程开发工具,分享一下我平常是如何用 V ...

  8. 从0开始,手把手教你开发并部署上线一个知识测验微信小程序

    上线项目演示 微信搜索[放马来答]或扫以下二维码体验: 项目源码 项目源码 其他版本 Vue答题App实战教程 Hello小程序 1.注册微信小程序 点击立即注册,选择微信小程序,按照要求填写信息 2 ...

  9. 手把手教你开发BLE数据透传应用程序

    如何开发BLE数据透传应用程序?什么是BLE service和characteristic?如何开发自己的service和characteristic?如何区分ATT和GATT?有没有什么工具可以对B ...

随机推荐

  1. web项目生成war包的问题

    今天面试一家公司,问我生成war包的命令是什么? 当时没明白,就说自己用的eclipse直接右键 export --->war 完了重启tomcat(第一种) 好久没用maven了.回来一查才明 ...

  2. 实现响应式——Bootstrap的删格系统详解

    Bootstrap 今天和大家一起学习如今很流行的前端框架之一,Bootstrap框架. 前言 今天带大家看看Bootstrap框架,其实我呢主要还是用里面的删格系统,单单这个删格系统就比较强大了.其 ...

  3. iOS 之 protocol的相关问题

    定义一个协议, 一个协议可以扩展子另一个协议 如果需要扩展多个协议中间使用逗号分隔 //定义一个协议 @protocol AnimalDelegate <NSObject, ***> @r ...

  4. 本地文件与服务器文件同步shell脚本。

    #!/bin/sh read -t 30 -p "请输入项目名:" name echo -e "\n" echo "项目名为:$name" ...

  5. code forces 436 C. Bus

    C. Bus time limit per test 2 seconds memory limit per test 256 megabytes input standard input output ...

  6. 磁盘管理之 raid 文件系统 分区

    第1章 RAID 磁盘阵列 1.1 使用raid的目的 1)获得更大的容量 2)让数据更安全 3)读写速度更快 1.2 raid0.raid1.raid5.raid10对比 磁头 0磁道 1扇区 前4 ...

  7. 0_Simple__cdpSimplePrint + 0_Simple__cdpSimpleQuicksort

    CUDA动态并行的简单实践,以及利用CUDA动态并行实现快排算法(有单线程的递归调用) ▶ 源代码:动态并行递归调用线程块 #include <iostream> #include < ...

  8. DOM遍历-祖先

    遍历 - 祖先 向上遍历 DOM 树 这些 jQuery 方法很有用,它们用于向上遍历 DOM 树: parent() parents() parentsUntil() jQuery parent() ...

  9. Python datetime之timedelta

    该函数表示两个时间的间隔 参数可选.默认值都为0:datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minut ...

  10. openstack学习心得:keystone 架构、概念、访问流程

    1.keystone 介绍及其组成 OpenStack Identity 服务提供了一个单一的功能集合,包括管理认证,授权和服务目录. Identity 服务通常作为和用户第一个交互的服务.一旦认证成 ...