Chrome插件开发实战

注意:google说2018年第一季度全面停用的 应用和 扩展不是一个东西,应用指的是 chrome apps 扩展指的是 chrome extension。

在几个月之前,我的一个朋友老张,跟我说了一个想法,看我能不能开发出这个东西,我刚刚开始的时候觉得很简单,做起来的时候阻力重重,最后不得不 不了了之了。

最近,觉得自己学会了点,就决定把这个东西做出来。边学边做,边做边学。最后终于做出了一个差不多的,特意写此文记录下,方便后来的过客。

缘起

有个团队(名字忘了)公布了制作守望先锋的视频集锦过程,讲到了他们如何用程序简化视频制作过程。老张看到了这个视频,就心生一念。开始构想如何用程序化简自己的视频制作流程。

在我知道他的视频制作过程之后,我觉得开发一个chrome插件最适合他现在情况。

插件的核心能力是找到网页中的视频下载url,并提供重命名的功能。而重命名的依据,就是依照在系统中预设的不同标签,生成的文件名。

初步探索

个人感觉 chrome 插件的开发应该是非常简单的,因为大学时期,有个朋友就自己写了一个插件自己使用,这件事情,让我感觉开发chrome插件还是比较简单的。

在chrome extension开发者的官网上,有get started 的范例,范例中会涉及插件开发最基本的内容。看完后,会有一个基本的认识。

同时,官网上面,还提供了丰富的demo,供使用者参考。搜了下download,找到了一个 download filename control 这个工具与我目前想做的插件非常近似,最终就是按照这个为雏形,进行的改造。

开发一

根据范例和官网的指引,第一步就是对chrome插件的核心配置manifest文件进行配置。chrome 官网提供了完整的说明,列出了所有可能包含在manifest文件中的配置信息。想要运行的位置不同,就有不同的配置方式。比方说在右上角的图标如何显示出来啊,点击弹出什么样的页面啊,是否把插件显示在地址栏啊,如何把js注入页面啊,等等,都是通过配置文件来来进行配置的。

大致计划是这样,我希望在指定的视频页面上显示插件内容,插件的内容是几个老张想要的分类按钮,一个下载按钮,插件还需要一个配置的页面,配置的页面添加分类,在打开视频页面的时候,会显示配置的分类按钮。

有了大概的规划之后,就在manifest中,找相关的配置代码。

实际的配置代码内容如下:

{
    "name": "CarVideoRenameHelper",
    "manifest_version": 2,
    "version": "0.1",
    "description": "help mr.zhang rename and download car video",
    "icons": {
        "16": "icon.png",
        "40": "icon.png",
        "128": "icon.png"
    },
    "author": "zhaogaz",
    "content_scripts": [{//这里是注入指定页面的代码配置,可以配置匹配的页面,注入的内容,启用的时间等等。
        "matches": [
            "https://wap.che.360.cn/*";, "http://v.xiaoyi.com/*";, "http://camera.leautolink.com/*";, "https://qsurl.goluk.cn/*";, "https://cdn.static.ddpai.com/*";
        ],
        "js": [
            "jquery-3.2.1.min.js", "content_js.js"
        ],
        "css": [
            "bootstrap.css", "content.css"
        ],
        "run_at": "document_start"
    }],
    "options_page": "options.html",//这里是配置页面的配置。
    "permissions": [
        "downloads",
        "storage",
        ""
    ],
    "background": {//这里是后台常驻的脚本配置,之后会说是怎么回事。
        "scripts": ["jquery-3.2.1.min.js", "bg.js"],
        "persistent": false
    }
}

以上有些内容是不得已才这么做的,暂时没有什么好的解决办法,后面会提到。

开发二

个人的开发习惯是从新增开始做,所以,我先做的配置页面,用惯了chrome浏览器的人可能都知道,在插件安装完事之后,会有一个选项按钮,在这个选项中,就可以对这个插件进行配置。我们要做的这个配置页面,正好就是这个选项。

因为第一步是从官方的demo中修改而来的,配置页面的html 的部分,就直接删了删不需要的代码就算做出来了。然后就是实现功能的js部分。最开始做的时候,由于js基本语法都不懂,就直接上来干的,写的node相关的操作。后来使用jquery进行了重构。这里就主要说下遇到的遇到的麻烦吧,有很多是新手性质的错误。

  • js执行的顺序和预期的不一致,打了几个不同的断点,最后才发现这个问题,因为这个问题导致先注册事件,然后才生成dom节点,最后导致事件不生效,确实是很尴尬。

  • 官方的范例中使用了localstorage保存配置,而我在取配置信息的时候,在这个部分找不到我需要的东西,所以就只能把配置信息存在别的地方。找了找官方的文档,发现有一个chrome.storage.local的东西,由于第一次用官方文档的东西进行使用,非常不熟练的,不过最后调试过多次之后,总算写出来了。

  • 由于后期的功能修改,做了一个拖拽换位的功能,仔细的研究了下拖拽的事件与相关的css效果,实现起来确实是有点困难,不过还是实现了基本能能力。

  • 有些时候会分不清js的dom对象和jquery的对象,不过多写一会就熟悉了。

  • jquery的使用还是有且奇怪,可能还是用的太少了。有些时候需要取jquery数组中的第一位才能使用,有些时候直接使用jquery数组的方法就能用。

开发三

这部分就是整个开发过程中最麻烦的部分了,manifest找了一圈,也没有找到如何在页面中注入html,只能选择在content 中的js中画出页面了。所以第一步就变成了用js画页面,早期我用原生的js 画了一个非常简陋的页面,基本是没法用的效果。

后期实在没办法使用了bootstrap的样式。画出来的时候觉得还挺满意的,等到注入到页面中一看,雪崩,由于注入的样式和js和 网页原先的样式冲突,最后花了一段时间大改,才把这个东西修好。下面就逐一说下遇到的困难和如何解决的。

  • 第一个问题就是插件使用content方式注入的css和网页的css互相冲突,网络上提供的解决办法就是使用iframe进行隔离。但是这个办法并不完美,因为这会导致整个页面的dom节点获取方式改变,修改起来还是比较麻烦的。其实还有一种方式就是把本地所有的css名字改了,只要不重名就没有问题,由于我是用的bootstrap自带的样式,也没有用这种方式。网络上还提供了一种方式就是使用shandow dom,没试过不做评价。

  • 在选择使用js 绘制页面之前,我没有想到其他的好方式,后来参考了下其他比较成熟的插件,发现,他们也都是用js来绘制页面的。(哈哈哈哈)

  • 比较困难的一个问题就是,如何在下载的时候进行重命名。最开始使用a标签,进行的尝试,但是失败了,由于chrome的特性导致的,如果a标签的链接跨域,那么a标签后面指定的download属性就会失效。最终的结果就是靠a标签是无法简单的进行重命名的。其中一个曲线的办法是,使用blob对象,来生成一个url,这样,浏览器就会忽略a标签跨域的问题,进行下载就成了。如何获得blob对象呢?需要用ajax的方式,把完整的视频内容都获取到,才能生成正确的blob对象,然后才能生成正确的url进行下载。

  • 而另一个比较困难的问题就是上面提到的ajax,在ajax中,xhr好像必须是https的方式才行,但是我要获得的视频链接,多数都不需要https,都是http,这就会导致js报错。然后程序没有办法继续进行。查了半天之后,解决办法就是在插件的background里面执行ajax,同时配置下manifest中的权限,也就是这句代码,这样就可以获取一个http的ajax了。

    "permissions": [
        "downloads",
        "storage",
        ""//这里
    ],
    "background": {//这里
        "scripts": ["jquery-3.2.1.min.js", "bg.js"],
        "persistent": false 
    }
  • 想要把ajax放到background 还需要解决一个问题,就是 background 和content之间的通信,因为我需要把下载的地址和文件名从content发送到 background里面,所以,我就需要一个通信,最开始的时候,在chrome api 文档中找到一个chrome.runtime.onMessage的方法。在content域调用onMessage,然后在background中注册一个onMessage.addListener即可进行监听。但是这个交互是即时的,无法把是否下载完成的状态返回到content中。于是我就在background中写了个onMessage 然后在content中注册了监听器,结果竟然不好使。然后试着使用长连接,也就是chrome.runtime.connect的方式,最终也解决了这个下载完成的反馈问题。

开发四

其实呢,以上内容基本把遇到的比较困难的东西说出来了,剩下的小问题还有不少,而且,我的实际开发过程是:

  • 先抄了一遍官方代码
  • 看了一个星期的原生js书
  • 然后写出了beta版本,给老张看了下,他提出了部分其他的需求,
  • 然后看了几天jquery和bootstrap,边看边试。
  • 然后每天下班写一会。上班划水的时候,招人随便问问。
  • 周六写了一天,把最后的问题都解决掉。又把额外的新功能加上。

以上过程才是我做这个程序的真实开发过程,需求基本都是合理的,不变态。主要欠缺的是自己的开发能力。在此基础上想一想,如何交互才能用着更爽,基本上会得到一个比较好的反馈。有时候还需要想一想怎么做既能减少工作量又能让操作“合理”。

还做了几个其他的小功能。

  • 比方说从指定的页面同步配置。
  • 在配置页面中加了一个预览。
  • 还根据要求修改了下页面的生成顺序。
  • 增加了一个备注框。

最后放几个效果图
Chrome插件开发实战_第1张图片
Chrome插件开发实战_第2张图片
Chrome插件开发实战_第3张图片

源码在这里:https://github.com/AngryDisk/360CarVideoDownloadHelper

第一次使用git,也用的不太明白。

就这样吧。想说的基本都说了。

你可能感兴趣的:(Chrome插件开发实战)