乐趣区

关于javascript:使用Vite搭建Chrome插件项目

前言

写了个 vite 插件,用于构建 Chrome Extension MV3 我的项目。我的项目已放在 github,详情请查看:vite-plugin-crx-mv3

如果对您有帮忙,star 反对一下,谢谢~

性能

  • Chrome 扩大页面和注入脚本反对应用 vue、react 等等;
  • Content_scripts 的 css 配置项反对.scss 或.less 文件;js 配置项反对.js(x)或.ts(x)文件;
  • background.service_worker 配置项反对.js 或.ts 文件;
  • 在开发环境,批改 content_scripts 和 background.service_worker 之后,content_scripts 注入的页面和 Chrome 扩大程序会主动重载;

应用

装置

# pnpm
pnpm add vite-plugin-crx-mv3 -D
# npm
npm install vite-plugin-crx-mv3 -D
# yarn
yarn add vite-plugin-crx-mv3 -D

vite 配置

import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'  // 如果是应用 vue 开发的,引入相干的插件
import crx from 'vite-plugin-crx-mv3'

export default defineConfig({
  plugins: [vue(),
    crx({manifest: './src/manifest.json'}),
  ],
})

demo:https://github.com/Jervis2049…

实现的整体思路

先回顾一下,一个根本的 Chrome 插件我的项目个别有哪些内容:

目录构造

├─assets        // 动态资源目录,寄存 icon,css 等等
├─content.js    //content_scripts,注入到页面的脚本
├─background.js //service_worker, 这是个运行在后盾的脚本
├─popup.html    //popup 弹框
├─menifest.json // 清单文件

menifest.json

{
  "name": "chrome-extension-demo",
  "description": "A Chrome extension demo.",
  "version": "1.0.0",
  "icons": {
    "16": "assets/icons/icon16.png",
    "48": "assets/icons/icon48.png",
    "128": "assets/icons/icon128.png"
  },
  "action": {
    "default_title": "Hello World",
    "default_popup": "popup.html"
  },
  "content_scripts": [{"matches": [ "<all_urls>"],
    "js": ["content.js"]
  }],
  "background": {"service_worker": "background.js"},
  "manifest_version": 3
}

这其中 version, manifest_version,name 为必填项。

好了,当初咱们都分明我的项目须要有什么了。这个 vite 插件就是以 manifest.json 作为一个入口文件,解析出外面的内容,比方 service_workercontent_scriptspopup.html 等等的门路。再通过这些失去的内容,利用构建工具打包出咱们想要的最终的文件。因而,配合上这个 vite 插件,本来只能配置原生 js,css 后缀的 manifest.json 反对了配置.ts(x)、.scss、.less 这样格局的文件了,因为这些都会在插件外部作解析的。这样,content_scripts 也实现了应用 vue、react 等等这样的技术栈开发了。

例如,配置了 tsx 文件:

...
"content_scripts": [{"matches": ["<all_urls>"],
    "js": ["content.tsx"],
}]
 ...

打包后是这样。产生的 css 文件会主动写入到配置:

...
"content_scripts": [{"matches": [ "<all_urls>"],
    "js": ["content.js"],
    "css": ["content.hashxxxx.css"],
}]
...

主动刷新性能

画了一个简略的流程图

先从开始的 vite build --watch 说起,为什么开发环境也要 build 呢?还是得解释一下,防止刚入门的小伙伴不了解。

开发步骤是这样的,首先关上chrome://extensions/, 右上角勾选“开发者模式”,而后点击“加载已解压的扩大程序”,加载我的项目。

然而,应用构建工具搭建的我的项目,都是初始文件,并没打包,这样是不能加载进去。平时咱们开发其它我的项目的时候,npm run dev运行后,并不会产生实体文件的,而是在内存里。所以在开发 Chrome 插件我的项目时就须要 build,生成 dist 目录,再点击“加载已解压的扩大程序”加载这个 dist 目录。vite 还提供了 watch 这个参数,批改文件后,会从新构建。如果你是用 webpack 搭建,达到雷同的成果,须要把 devServer.writeToDisk 设置为 true,writeToDisk 意为写入到磁盘。

到了这步,只管 watch 到文件批改,会从新打包。然而 Chrome 插件并不会感知到文件已发生变化。content_scripts 和 service_worker 是不会自动更新的。通常都须要手动到后盾刷新一下。这很不不便,于是实现了批改文件,主动重载的性能。Chrome 提供了 chrome.runtime.reload 办法,能够利用这个做文章。

首先咱们须要晓得,content_scripts、service_worker、popup 这三者是能够相互通信的。插件利用了 content_scripts 和 service_worker 之间的消息传递,从而达到刷新的目标。

//content_scripts 发送音讯
chrome.runtime.sendMessage({msg: 'RELOAD'}, () => {window.location.reload() //service_worker 回传音讯给 content_scripts 的回调
})
//service_worker 接管音讯
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {if (request.msg == 'RELOAD') {chrome.runtime.reload() // 重载 Chrome 插件
    sendResponse() // 回传音讯给 content_scripts}
})

content_scripts 是注入到页面的脚本,所以 Chrome 插件重载之后,才调 window.location.reload() 让页面刷新。

vite-plugin-crx-mv3 插件,在开发环境会把上述代码别离写入到 content-dev.js 和 background-dev.js(如果用户没配置 service_worker 才会生成 backgound-dev.js。如果配了,就把 chrome.runtime.onMessage.addListener 那段代码,在 transform 钩子阶段插入到原有的 background.js)。同时也会写入到 manifest.json 配置文件。

...
"content_scripts": [{"matches": ["<all_urls>"], // 设置为 <all_urls>,这样所有页面都会加载到
    "js": ["content-dev.js"],
}]
"background": {"service_worker": "background-dev.js"},
 ...

到这步曾经筹备得差不多了。咱们的最终目标是,批改文件后,从新打包产出新的文件,而后 Chrome 插件能够主动刷新。vite build --watch曾经实现一部分了。主动刷新的性能是应用 websocket 帮助实现的,批改文件每次从新打包后,发送 socket 音讯给客户端,客户端再接管音讯。在 vite 插件的 writeBundle 阶段操作(其实是 rollup 的钩子),在这阶段示意曾经构建实现,文件写入实现。

writeBundle(){
   // 发送音讯给客户端(content-dev.js)//content-dev.js 外面接管到音讯后,就走下面和 service_worker 通信的流程了。}

写在最初

这个 vite 插件根本满足本人现阶段的开发需要,其实开发 Chrome 插件的教训并不是很多,可能有些场景还没笼罩,请多多包涵。如果应用过程有什么问题,能够告知我。创作不易,如果能帮到您,能够 star 反对一下~

退出移动版