如何开发一个google插件

2023-12-21 15:34:57

今天我介绍一下如何开发一个google插件,这篇文章主要是介绍一下整体的框架,具体细节不会过多讲解。

一、什么是google插件

google插件是安装在google浏览器中的扩展程序,这个扩展程序也是基于html、css、js开发而来的,并且浏览器提供了额外的API供扩展程序使用。



目前最新插件API版本是v3,v2版本会逐步被淘汰(网络上大部分插件api教程都是基于v2版本的,v3版本有很多不兼容变化,此次分享为v3版本)
在这里插入图片描述
开发的google插件可以应用到以Chromium为内核的浏览器中,如360浏览器、qq浏览器等

二、google插件可以做什么

google插件可以做什么主要是看google插件提供什么样功能的API:google api
● tabs:浏览器窗口操作功能:增删改查截图等
● cookie:cookie操作功能
● network:网络拦截功能

● 书签控制;
● 下载控制;
● 窗口控制;
● 标签控制;
● 网络请求控制,
● 各类事件监听;

三、如何开发google插件

插件本身是使用html、js、css构成
在这里插入图片描述

1.插件组成结构
  1. 配置文件manifest.json
  2. 后台脚本background.js
  3. 交互弹框popup.html、popup.js、popup.css
  4. content_script.js

1.配置文件主要是配置关于插件的信息,比如版本、icon、权限配置等。
2.后台脚本background.js主要是一个全局的js逻辑,如果你的插件不需要全局的js逻辑,这个文件可不需要
3.交互弹框是插件和用户交互的逻辑,本质就是一个弹窗html
4.content_script是操作网页的js,如果插件没有对网页的操作逻辑也可不需要

2.生命周期和环境

后台脚本在浏览器打开时一直存在,在浏览器关闭后卸载。注意background虽然是js但是它并不存在window、document、XHR、DOM等对象,可以理解为background是浏览器环境(background可访问Chrome对象、fetch)
交互弹框popup.js是在插件点击打开弹框后存在,弹框关闭后卸载。它有dom环境,但是它只能访问popup.html的DOM
content_script.js是插入到网页中的js,所以它能访问和操作网页中的DOM元素,content_script使用分为两种方式:静态插入和动态插入

3.如何结合框架使用(react/vue)

一个基本插件只包含上述的html、js、css。若用原始的方式去开发插件是非常影响效率,我们需要自己去操作很多的dom,并且npm包也不能直接使用
我们可以用npm、ts、react开发插件,然后使用webpack去打包。
这里注意一点:webpack一般只有一个入口文件,但是background.js和content_script.js并不会在popup.js中引入,所以webpack的配置也是多入口配置

const path = require("path");

module.exports = {
  entry: {
    main: "./src/main.tsx",
    content_script: "./src/content_script.ts",
    background: "./src/background.ts",
  },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "dist"),
    clean: true,
  },
  mode: "production",
  resolve: {
    extensions: [".js", ".jsx", ".ts", ".tsx"],
    alias: {
      "@": path.resolve(__dirname, "src"), // 这样配置后 @ 可以指向 src 目录
    },
  },
  // stats: 'summary',
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.(tsx|ts)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-react",
              [
                "@babel/preset-typescript",
                {
                  isTSX: true,
                  allExtensions: true,
                },
              ],
            ],
          },
        },
      },
    ],
  },
};

在popup.html中引入打包后的popup.js

当然,在manifest中配置的background和content_script也是打包后的js

4.插件之间的通信

插件通信是google插件开发的一个难点,一定要弄清楚几种类型js之间是如何通信的
场景:
1.有个插件功能是点击一个按钮,网页自动滚屏
2.在background中截屏了网页,但是background中没有DOM元素,如何进行下载图片
3.网页中进行了某些操作,将操作结果回显到popup中

在开发插件时因为生命周期和环境的不同,我们会去使用不同作用的js:background.js、content_script.js和popup.js。当不同类型的js需要通信时,如何进行通信?

google插件通过通信机制,使不同类型js进行通信。消息可以包含任何有效的 JSON 对象(null、布尔值、数字、字符串、数组或对象)。有两种消息传递 API:一种用于一次性请求,另一种更复杂,用于允许发送多条消息的长期连接。官网google插件通信

在这里插入图片描述

短连接(单条发送)

content_script发送信息

(async () => {
  const response = await chrome.runtime.sendMessage({greeting: "hello"});
  // do something with response here, not outside the function
  console.log(response);
})();

background或popup接收信息并响应

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting === "hello")
      sendResponse({farewell: "goodbye"});
  }
);

background发送信息(需要指定发送到哪个窗口)

(async () => {
  const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
  const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});
  // do something with response here, not outside the function
  console.log(response);
})();
长链接

popup/content_script接收和发送信息

var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
  if (msg.question === "Who's there?")
    port.postMessage({answer: "Madame"});
  else if (msg.question === "Madame who?")
    port.postMessage({answer: "Madame... Bovary"});
});

background监听信息

chrome.runtime.onConnect.addListener(function(port) {
  console.assert(port.name === "knockknock");
  port.onMessage.addListener(function(msg) {
    if (msg.joke === "Knock knock")
      port.postMessage({question: "Who's there?"});
    else if (msg.answer === "Madame")
      port.postMessage({question: "Madame who?"});
    else if (msg.answer === "Madame... Bovary")
      port.postMessage({question: "I don't get it."});
  });
});

文章来源:https://blog.csdn.net/qq_37860930/article/details/135130830
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。