迁移到 Plasmo 框架
Plasmo 浏览器扩展框架通过声明式方法简化了浏览器扩展的构建。它消除了样板代码,并提供了一个易于理解、使用和退出的基于文件的配置系统。
在本指南中,我们将引导您从任何扩展项目迁移到 Plasmo,并突出显示您需要进行的一些关键更改。
安装 Plasmo CLI
Plasmo 框架的主要驱动程序是 Plasmo CLI。这是一个 Node.js 包,包含编译器、打包器、开发服务器和为浏览器扩展量身定制的打包器:
pnpm install plasmo
要启动开发服务器,请运行 plasmo dev
。要构建扩展,请运行 plasmo build
。要打包扩展,请运行 plasmo package
。
manifest.json
Plasmo 将 manifest.json
合并到 package.json
中,并抽象掉最基本的属性:
Manifest 字段 | 抽象化 |
---|---|
icons | 自动生成带有 assets 目录中的 icon.png 文件 |
action , browser_actions | popup.tsx |
options_ui | options.tsx |
content_scripts | contents/*.{ts,tsx} , content.ts , content.tsx |
background | background.ts |
sandbox | sandbox.tsx , 沙盒页面 |
manifest_version | 由 --target 构建标志设置,默认为 3 |
version | 由 package.json 中的 version 字段设置 |
name | 由 package.json 中的 displayName 字段设置 |
description | 由 package.json 中的 description 字段设置 |
author | 由 package.json 中的 author 字段设置 |
homepage_url | 由 package.json 中的 homepage 字段设置 |
Plasmo 在 package.json
和 manifest.json
之间集中常见的元数据,并自动解析任何静态文件引用(如操作、后台、内容脚本等)。
这使您可以专注于重要的元数据,例如名称、描述、OAuth、declarative_net_request 等。
此外,它使框架能够提供更强大的功能,例如:
弹出窗口、选项、新标签页
Plasmo 去除了手动挂载 React/Svelte/Vue 组件的需求。
在一个非 Plasmo 扩展项目中,为了挂载一个 React 组件,您需要创建一个 index.html
模板和相关的 JavaScript 代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>弹出窗口</title>
</head>
<body>
<div id="root"></div>
<script src="popup.js"></script>
</body>
</html>
import { createRoot } from "react"
import Popup from "./core/popup"
const root = document.getElementById("root")
createRoot(root).render(<Popup />)
如果您想添加 TypeScript、LESS 或 SCSS,则需要使用 Webpack、Parcel 或 ESBuild,并设置额外的插件和加载器。
使用 Plasmo 框架,这变得更加简单。只需在源代码目录中添加一个 popup.tsx
或 options.tsx
文件,并导出默认的 React 组件。
Plasmo 会处理其余的工作:
import Popup from "./core/popup"
export default Popup
Plasmo 内置支持 CSS、SCSS、LESS、CSS Modules 和 PostCSS 插件。
例如,如果您想使用 SCSS,只需在您的 React 组件中导入 SCSS 文件:
import Popup from "./core/popup"
import "./popup.scss"
export default Popup
您可以以这种方式挂载 React 组件用于选项页面、新标签页、沙盒页面和任何其他自定义页面。
自定义页面
在非 Plasmo 扩展项目中,创建自定义页面通常需要额外的 HTML 模板和关联的 JavaScript 代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>自定义页面</title>
</head>
<body>
<div id="root"></div>
<script src="./custom.js"></script>
</body>
</html>
import { createRoot } from "react"
import CustomPage from "./core/custom-page"
const root = document.getElementById("root")
createRoot(CustomPage).render(<PopupApp />)
使用 Plasmo,您可以使用内置的标签页功能轻松创建自定义页面。在源代码目录中添加一个 tabs
文件夹,并将您的自定义页面放在那里,使用 .tsx
文件:
import Hello from "./core/hello"
export default Hello
该页面将在 chrome-extension://<extension-id>/tabs/custom.html
处可用。
内容脚本
在非 Plasmo 扩展项目中,您需要在 manifest.json
文件中指定内容脚本并用 JavaScript 编写它们:
{
"content_scripts": [
{
"matches": ["https://*/*", "http://*/*"],
"all_frames": true,
"css": ["content.css"],
"run_at": "document_start"
}
]
}
console.log("Hello from content script!")
使用 Plasmo,您可以在名为 content.ts
的文件或名为 contents
的目录中指定内容脚本及其相应的配置 - 更多内容请参见后文!
这是 content.ts
文件的样子:
import type { PlasmoCSConfig } from "plasmo"
export const config: PlasmoCSConfig = {
matches: ["https://*/*", "http://*/*"],
all_frames: true,
css: ["~content.css"]
}
console.log("Hello from content script!")
无需在 manifest.json
和 content.js
文件之间来回切换。附加的好处是配置是完全类型的,因此可以从您的 IDE 获得有价值的自动补全。
要添加多个内容脚本,请创建一个名为 contents
的目录并重复上述步骤。您可以随意命名此目录中的脚本。它们都将作为具有自己配置的内容脚本添加。
例如,假设您想添加一个将页面背景颜色更改为绿色的内容脚本。您可以通过在 contents
目录中创建一个名为 emerald-splash.ts
的文件来实现:
document.body.style.backgroundColor = "green"
由于内容脚本文件未导出配置,Plasmo 将使用默认配置:
{
"matches": ["<all_urls>"]
}
内容脚本 UI
如果要在网页中注入 React 组件,您的扩展可能有很多样板代码,创建 Shadow DOM、找到正确的元素挂载到、MutationObservers 等。
我们已经将所有这些抽象出来,以便您可以专注于构建组件,而无需担心其余部分。
例如,假设您想在网页中注入一个简单的按钮 React 组件。您可以通过在 contents
目录中创建一个名为 press-me.tsx
的文件来实现:
export default function PressMeCSUI() {
return <button>Press me</button>
}
Plasmo 将自动将此组件注入到页面中,并将其挂载到页面的根元素上。
如果要将组件注入到特定元素中,可以通过从文件中导出 getInlineAnchor
函数来实现:
import type { PlasmoGetInlineAnchor } from "plasmo"
export const getInlineAnchor: PlasmoGetInlineAnchor = async () =>
document.querySelector("#pricing")
通过返回一个 Element,Plasmo 将组件挂载到该元素旁边。您可以完全自定义挂载行为、组件渲染方式等。
此功能称为内容脚本 UI。要了解更多关于其 API 和工作原理,请查看技术文档中的生命周期。
您还可以指定组件相对于要挂载的元素的插入位置:
import type { PlasmoGetInlineAnchor } from "plasmo"
export const getInlineAnchor: PlasmoGetInlineAnchor = async () => ({
element: document.querySelector("#pricing"),
insertPosition: "afterend"
})
后台服务工作者
在非 Plasmo 项目中,创建后台服务工作者需要在 manifest.json
文件中指定 background
属性并用 JavaScript 编写服务工作者代码:
{
"background": {
"service_worker": "background.js"
}
}
console.log("Hello from BGSW!")
在 Plasmo 中,您通过创建一个名为 background.ts
的文件来指定后台服务工作者:
console.log("Hello from BGSW!")
您可以导入任何针对标准服务工作者运行时的模块到 background.ts
中。例如,您可以添加 bip39
模块:
import { generateMnemonic } from "bip39"
console.log(
"Live now; make now always the most precious time. Now will never come again."
)
console.log(generateMnemonic())
Plasmo 将自动打包 background.ts
文件并将其作为后台服务工作者添加到 manifest.json
文件中。
环境变量
如果您当前正在使用环境变量,您可以在 Plasmo 中继续使用它们。
Plasmo 框架支持开箱即用的环境变量,无需额外设置。
退出 Plasmo
Plasmo 框架的抽象理念是去除最常见的配置和样板代码。这使得开发人员可以在更高的抽象层工作——他们选择的 UI 库/框架,例如 React、Vue 和 Svelte。这是创建更强大和美丽的扩展的路径。
退出 Plasmo 非常简单,只需从您的 package.json
文件中删除 plasmo
依赖项并将您的组件移至自定义设置即可。这是因为 Plasmo 生成的所有胶水代码都在框架编译器和打包器层注入,从而使您的功能代码极具可移植性。
您还可以根据需要尽可能多地使用 Plasmo。所有 chrome API 都可用,您可以直接在功能代码中使用它们。例如,您可以直接使用 chrome.runtime.messaging
API 而不是使用messaging API。内容脚本和扩展页面也是如此。