黑白梦

通过 plasmo 创建浏览器扩展程序

使用 Plasmo,只需编写 React 组件,即可创建浏览器扩展程序。

https://docs.plasmo.com/

创建项目

通过以下命令,创建基础的 Plasmo 浏览器扩展项目结构:

npm create plasmo

创建文件:

  • 创建了一个 package.json 文件,与普通项目比起来,多了一个 “manifest” 属性,可自定义插件相关信息。
  • 创建了一个 popup.tsx 文件,用于编写插件代码。

开发与加载扩展

执行命令

npm run dev

在 Chrome 中加载扩展程序:到扩展管理中加载解压缩的拓展,加载 build/chrome-mv3-dev 目录。

扩展页面创建

https://docs.plasmo.com/framework/ext-pages

创建这些文件,正常编写 React 代码即可。

  • 弹出页面 popup.tsx
  • 选项设置页 options.tsx
  • 开发工具页 devtools.tsx
  • 新标签页 newtab.tsx

注入内容脚本

插件往往需要注入到网页中,通过内容脚本来实现。

我们创建 content.tsx ,注入 UI 界面。

设置匹配域名时启用,如仅在本站博客文章页面使用:

import type { PlasmoCSConfig } from "plasmo"

export const config: PlasmoCSConfig = {
  matches: ["https://heibaimeng.com/post/*"]
}

导出组件,里面编写需要注入的 UI 内容:

export default () => (
  <div>
    <button onClick={() => alert("hello")}>hello</button>
  </div>
)

默认注入到 body,使用 Overlay (绝对定位)的方式。可通过钩子改为 Inline 模式,直接插到某个节点旁:

export const getInlineAnchor: PlasmoGetInlineAnchor = async () =>
  document.querySelector(/* ... */)

打开控制台,可以发现组件挂载在 plasmo-csui 这个 web components 的 shadow-root 内了。所以直接加载 css 只会影响原页面,不会影响注入的 UI 内容,需要通过钩子 加载 CSS:

import cssText from "data-text:./content.css"

export const getStyle = () => {
  const style = document.createElement("style")
  style.textContent = cssText
  return style
}

可以自行指定 shadow host id,方便 dom 操作:

const HOST_ID = "heibaimeng-shadow-host"
export const getShadowHostId = () => HOST_ID

// dom 操作
document.getElementById(HOST_ID).shadowRoot

官方示例

https://github.com/PlasmoHQ/examples/tree/main