• chrome插件开发(manifest_version版本V3 + Ant Design Vue)


    1.什么是 Chrome 插件

    谷歌浏览器插件是一种小型的定制浏览器体验的程序,通过插件可以自定义浏览器的一些行为来适合个人的需求,例如上面的查看服务器状态插件。
    在应用商店中下载下来的插件基本上都是以.crx 为文件后缀,该文件其实就是一个压缩包,包括插件所需要的 HTML,Javascript,CSS 、图片资源等等文件。
    开发 Chrome 插件只需要会 HTML,Javascript,CSS 就可以动手开发了。

    2.基础概念

    2.1 基本原理
    下面这张图很好的可以理解 Chrome 插件的原理。
    在这里插入图片描述

    2.2 文件的目录

    │  manifest.json
    ├─html
    │   index.html
    ├─images
    │   icon-128.png
    │   icon-48.png
    │   icon-16.png
    ├─scripts
    │   background.js
    ├─styles
    │   main.css
    └─_locales
        ├─en
        │  messages.json
        └─zh_CN
            messages.json
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • manifest.json 是整个插件的功能和文件配置清单,非常重要
    • images 存放的为插件的图标文件
    • _locales 存放的为插件的国际化语言脚本
    • scripts 存放的为 js 文件
    • styles 存放的为样式文件
    • html 存放的 html 文件

    着重说一下 manifest.json 文件

    {
      // 清单文件的版本
      "manifest_version": 3,
      // 插件的名称
      "name": "all in plugin",
      // 插件的版本
      "version": "2.0.0",
      // 插件描述
      "description": "all in plugin",
      // 图标
      "icons": {
        "16": "assets/icon16.png",
        "48": "assets/icon48.png",
        "128": "assets/icon128.png"
      },
      //背景页,后台脚本引入,v2是scripts:[xxx,xxx],可以引入多个js文件,v3是service_worker:'xxx',只能引入一个js,v3版最大的改动应该就是这里了,扩展程序管理界面的插件的那个“背景页”也将变成“Service Worker”,改动之后background.js将和浏览器完全分离,即无法调用window和ducoment对象
      //可以看介绍:
      //1、//developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/#background-service-workers;
      //2、//developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/
      "background": {
        "service_worker": "js/background.js"
      },
      "action": {
        "default_icon": {
          "19": "assets/icon19.png",
          "38": "assets/icon38.png"
        },
        "default_title": "all in plugin",
        "default_popup": "popup.html"
      },
      //注入脚本,值是个数组对象,可以有多个对象
      "content_scripts": [
        //每个对象代表一个注入的配置
        {
          //需要注入js脚本文件的指定页面
          "matches": ["http://*/*", "https://*/*"],
          "css": [],
          //需要在指定页面注入的js脚本文件
          "js": [
            "js/chunk-vendors.js",
            "js/jquery-1.8.3.js",
            "js/google-csdn.js",
            "js/monitor-help.js"
          ],
          //不允许注入js脚本文件的指定页面
          //  "exclude_matches": ["https://*.xxx.com/*"],
          //什么时候注入的js脚本,document_start=页面加载开始时,document_end=页面加载结束时
          "run_at": "document_start"
        }
      ],
      //API权限,需要使用某些API时需要设置该API权限才行
      "permissions": [
        "contextMenus",
        "tabs",
        "notifications",
        "webRequest",
        "storage"
      ],
      //主机权限,在背景页backgroud.js里面或者popup页面走请求时,请求域名的白名单权限,如果没添加的则请求会失败
      "host_permissions": ["http://*/*", "https://*/*"],
      //  免费广告位
      "homepage_url": "",
      // devtools栏页面
      "devtools_page": "devtools.html",
      //内容安全政策,V2的value是字符串,V3是对象
      "content_security_policy": {
        //原文:此政策涵盖您的扩展程序中的页面,包括 html 文件和服务人员;具体不是很明白,但是参数值得是self,即当前自己
        "extension_pages": "script-src 'self'; object-src 'self'"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    3. Hello world

    创建 manifest.json 文件,添加基本的配置

    {
        "name": "hello-world-plugin",
        "description" : "hello-world-plugin",
        "version": "1.0.0",
        "manifest_version": 3,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里我们定义了当前的插件名字 all in plugin,插件的描述和插件的版本。

    注意:verison 在插件打包之后,后面可以根据版本号来判断插件是否需要更新。

    给自己的插件添加一个浏览器右上角的图标
    在这里插入图片描述
    增加 html

    继续修改我们的 manifest.json 文件

    {
      "description": "hello-world-plugin",
      "manifest_version": 3,
      "name": "hello-world-plugin",
      "version": "1.0.0",
      "action": {
        "default_icon": {
          "19": "assets/icon19.png",
          "38": "assets/icon38.png"
        },
        "default_popup": "popup.html",
        "default_title": "hello-world-plugin"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    我们的 html 文件

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width,initial-scale=1.0" />
        <title>hello-world-plugintitle>
    head>
    
    <body>
    hello-world-plugin
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.安装插件

    找到我们的扩展程序,如下图所示
    在这里插入图片描述
    点击 加载以解压的扩展程序
    在这里插入图片描述
    安装后,点击我们的扩展程序图标,我们就可以看到我们的 html 内容了

    5.创建 Vue 项目

    当前 Vue3 已经相对趋于稳定,很多公司和个人都开始尝鲜使用其进行开发,那么我们今天也以 Vue3 进行搭建学习。

    使用 vue-cli 创建 vue3.x 版本的 vue 项目 vue create hello-world-plugin:

    vue create hello-world-plugin
     Default ([Vue 2] babel, eslint) 
    > Default (Vue 3) ([Vue 3] babel, eslint) 
     Manually select features
    
    • 1
    • 2
    • 3
    • 4

    回车之后,我们选择 Default (Vue 3) ([Vue 3] babel, eslint),不过如何喜欢用自己配置的可以选择第三条。

    cd hello-world-plugin
    npm run serve
    
    • 1
    • 2

    常规的项目跑起来之后可以在浏览器看到基本的页面
    在这里插入图片描述

    此时的项目结构目录大致为

    ├── README.md
    ├── babel.config.js
    ├── package.json
    ├── public
    │   ├── favicon.ico
    │   └── index.html
    ├── src
    │   ├── App.vue
    │   ├── assets
    │   │   └── logo.png
    │   ├── components
    │   │   └── HelloWorld.vue
    │   └── main.js
    └── package-lock.json
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    5.1. 修改项目目录

    删除 main.js、App.vue、components 以及文件夹下的 HelloWorld.vue、logo.png、public 文件
    在根目录下创建 vue.config.js 的 vue 配置文件
    从阿里巴巴矢量图标库 下载自己想要的图标文件,用了 16、48、128 这三种大小的图标,将下载的图标放到 src/assets 下面。
    src 文件夹下面创建 background、plugins、popup、utils 文件
    在 popup 文件夹下面创建 components、main.js 和 index.html,在 components 文件夹下创建 App.vue
    在 plugins 文件夹下创建 inject.js 和 manifest.json
    在 background 下面创建 main.js 文件
    那么修改后的项目目录:

    ├── src
    │   ├── assets
    │   │   ├── icon128.png
    │   │   ├── icon16.png
    │   │   └── icon48.png
    │   ├── background
    │   │   └── main.js
    │   ├── main.js
    │   ├── plugins
    │   │   ├── inject.js
    │   │   └── manifest.json
    │   ├── popup
    │   │   ├── components
    │   │   │   └── app.vue
    │   │   ├── index.html
    │   │   └── main.js
    │   └── utils
    ├── vue.config.js
    └── package-lock.json
    ├── README.md
    ├── babel.config.js
    ├── package.json
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    vue.config.js
    vue.config.js 文件作为 vue 项目打包,运行等的基本配置,主要功能是打包成为我们 Chrome 插件所需要的项目目录。

    添加 copy-webpack-plugin 模块,主要是用来拷贝文件
    // 安装

    npm install copy-webpack-plugin@6.0.2 -save-dev
    
    • 1

    配置 vue.config.js

    const CopyWebpackPlugin = require("copy-webpack-plugin");
    const path = require("path");
    
    // 复制文件到指定目录
    const copyFiles = [
     {
         from: path.resolve("src/plugins/manifest.json"),
         to: `${path.resolve("dist")}/manifest.json`
       },
       {
         from: path.resolve("src/assets"),
         to: path.resolve("dist/assets")
       },
       {
         from: path.resolve("src/plugins/inject.js"),
         to: path.resolve("dist/js")
       }
    ];
    
    // 复制插件
    const plugins = [
       new CopyWebpackPlugin({
         patterns: copyFiles
       })
    ];
    
    // 页面文件
    const pages = {};
    // 配置 popup.html 页面
    const chromeName = ["popup"];
    
    chromeName.forEach(name => {
       pages[name] = {
         entry: `src/${name}/main.js`,
         template: `src/${name}/index.html`,
         filename: `${name}.html`
       };
    });
    
    module.exports = {
     pages,
     productionSourceMap: false,
     // 配置 content.js background.js
     configureWebpack: {
      entry: {
       background: "./src/background/main.js"
      },
      output: {
       filename: "js/[name].js"
      },
      plugins
     },
     // 配置 content.css
     css: {
      extract: {
       filename: "css/[name].css"
      }
     }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    popup/index.html
    index.html 我们只是将原来的 public 文件夹下的 index.html 文件内容拷贝过来。

    DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <title>my-vue-chrome-plugintitle>
      head>
      <body>
        <noscript>
          <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.strong>
        noscript>
        <div id="app">div>
        
      body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    popup/main.js
    这个是 vue 项目的入口配置文件,将原来的 main.js 复制过来

    import { createApp } from 'vue'
    import App from './components/App.vue'
    createApp(App).mount('#app')
    
    • 1
    • 2
    • 3

    popup/components/App.vue
    正常的 vue 文件

    <template>
      <div>hello world</div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    background/main.js
    简单打印一下
    console.log(‘hello world background’)

    5.2 打包

    npm run build
    可以看到打印台已经完成打包
    在这里插入图片描述

    此时的项目目录

    .
    ├── README.md
    ├── babel.config.js
    ├── dist
    │   ├── assets
    │   │   ├── icon128.png
    │   │   ├── icon16.png
    │   │   └── icon48.png
    │   ├── js
    │   │   ├── background.js
    │   │   ├── chunk-vendors.fa86ccee.js
    │   │   ├── inject.js
    │   │   └── popup.js
    │   ├── manifest.json
    │   └── popup.html
    ├── package.json
    ├── src
    │   ├── assets
    │   │   ├── icon128.png
    │   │   ├── icon16.png
    │   │   └── icon48.png
    │   ├── background
    │   │   └── main.js
    │   ├── plugins
    │   │   ├── inject.js
    │   │   └── manifest.json
    │   ├── popup
    │   │   ├── components
    │   │   │   └── app.vue
    │   │   ├── index.html
    │   │   └── main.js
    │   └── utils
    ├── vue.config.js
    └── package-lock.json
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    5.3 加载插件

    在 Chrome 插件中加载已解压的扩展程序 ,选择我们的 dist 文件,发现无法加载
    在这里插入图片描述
    是因为缺少了可以执行的 js 文件,因此将我们打包生成的 js/chunk-vendors.js 文件放到 manifest.json 文件里面

     "content_scripts": [
      {
       "matches": ["http://*/*", "https://*/*"],
       "css": [],
          "js": ["js/chunk-vendors.js"], // 修改
       "run_at": "document_idle"
      }
     ],
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    再进行打包加载,即可发现我们的插件已经成功安装

    6.引入Ant Design Vue

    参考 Ant
    Design Vue快速上手

    使用 npm 或 yarn 安装 #
    我们推荐使用 npm 或 yarn 的方式进行开发,不仅可在开发环境轻松调试,也可放心地在生产环境打包部署使用,享受整个生态圈和工具链带来的诸多好处。

    $ npm install ant-design-vue --save
    $ yarn add ant-design-vue
    
    • 1
    • 2

    修改popup下index.html

    DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width,initial-scale=1.0" />
        <title>my-vue-chrome-plugintitle>
    head>
    
    <body>
        <noscript>
            <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
                    properly without JavaScript enabled. Please enable it to
                    continue.strong>
        noscript>
        <div id="app">div>
        
    body>
    
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    修改popup/components下App.vue文件

    <template>
      <a-button type="primary">Primary Button</a-button>
      <a-button>Default Button</a-button>
      <a-button type="dashed">Dashed Button</a-button>
      <a-button type="text">Text Button</a-button>
      <a-button type="link">Link Button</a-button>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    重新构建,刷新插件
    成功展示!
    在这里插入图片描述

    注意点

    1. manifest.json v2和v3版本差异特别大,需要按照v3规范来配置
    2. v3版本权限控制更严,不支持插件热更新来测试
    3. 默认构建后js、css都是格式、混淆格式,不方便debug,可以通过修改vue.config.js添加下面配置还原:

      chainWebpack(config) {
        config.optimization.minimize(false);
      }
    
    • 1
    • 2
    • 3
  • 相关阅读:
    leetcode 2602. 使数组元素全部相等的最少操作次数
    山区自建房BCD浪涌保护器接线方案(自建房用电防雷)
    python折半查找
    学习-Java数组之Arrays类操作数组之填充替换数组元素
    依托数据、平台、知识增强等优势 夸克大模型大幅降低问答幻觉率
    通用监控视频web播放方案
    面向对象——实现类的基本操作
    PyQt5_pyqtgraph双均线组合工具
    【MySQL篇】事务相关知识点总结(全)
    【前端精进之路】JS篇:第3期 执行上下文
  • 原文地址:https://blog.csdn.net/Primary_wind/article/details/128053613