内容脚本
内容脚本在网页的 隔离世界 中运行。这允许来自各种扩展的多个内容脚本共存,而不会相互冲突,并且与页面的 JavaScript 保持隔离。
以 .ts
结尾的脚本不会捆绑前端运行时(react/vue/svelte),也不会被视为 UI 脚本,而以 .tsx
、.vue
或 .svelte
结尾的脚本则会被视为 UI 脚本。
使用场景:
- 从当前网页抓取数据
- 选择、查找和样式化当前网页中的元素
- 向当前网页注入 UI 元素
- 向“主世界”上下文中注入代码
添加单个内容脚本
由于 Plasmo 的默认 TypeScript 配置将所有源文件视为模块,如果你的代码中没有任何导入或导出,则需要在文件开头添加 export {}
行。(当你创建第一个内容脚本时会看到此警告!)
创建一个 content.ts
文件,导出一个空对象并开始编写代码!
export {}
console.log(
"你可能会发现,拥有并不是一件像渴望那样令人愉悦的事情。这并不合逻辑,但通常是真实的。"
)
重新加载你的扩展程序,打开一个网页,然后打开其检查器:
请参阅 with-content-script (opens in a new tab) 获取完整示例。
添加多个内容脚本
为多个内容脚本创建一个 contents
目录,并将你的内容脚本添加到其中。确保它们的名字描述了它们的功能!
请参阅 with-many-content-scripts (opens in a new tab) 获取示例。
配置
有时,你希望在某些页面上运行内容脚本。你可以通过从内容脚本中导出配置对象来提供自定义内容脚本配置:
import type { PlasmoCSConfig } from "plasmo"
export const config: PlasmoCSConfig = {
matches: ["<all_urls>"],
all_frames: true
}
使用导出的 PlasmoCSConfig
类型处理此配置对象非常简单 🥳。
要了解更多关于配置及其每个属性的信息,请查阅 Chrome 的官方文档 (opens in a new tab)。
注入到主世界
要从内容脚本修改 window
对象,必须将代码注入到“主世界”。
从 Plasmo v0.65.0
开始,Plasmo 内容脚本可以在配置中指定 world
属性:
import type { PlasmoCSConfig } from "plasmo"
export const config: PlasmoCSConfig = {
matches: ["<all_urls>"],
world: "MAIN"
}
上述脚本将被注入到主世界。
要手动注入主世界脚本,请使用 chrome.scripting.executeScript
API。首先,在 package.json 的 'manifest.permissions' 数组 中手动添加脚本权限:
{
...
"manifest" : {
"permissions": ["scripting"]
}
}
然后,通过调用 chrome.scripting.executeScript
将内容脚本注入到主世界:
chrome.scripting.executeScript(
{
target: {
tabId // 你想注入的标签页
},
world: "MAIN", // MAIN 用于访问 window 对象
func: windowChanger // 要注入的函数
},
() => {
console.log("后台脚本在注入后收到回调")
}
)
对于 func
键,你可以传递项目中的 TS 函数。当扩展程序打包时,它将被转译为 JS。你还可以使用 files
键从构建包的根目录注入文件。
func
的作用域是紧密封装的。你无法直接在函数内使用作用域外声明的变量或任何导入的变量。但是,你可以使用传递给 args
属性的变量。确保仅使用 JSON 可序列化的值。
请参阅 with-main-world (opens in a new tab) 获取示例。
获取外部 API 和 CORS
由于内容脚本在网页的上下文中运行,因此受同源策略限制。要缓解 CORS 限制,可以使用 Plasmo 消息传递 API 通过后台服务工作线程代理请求。
导入资源
要将外部资产导入到内容脚本中,可以使用 url:
方案:
import myFile from "url:./path/to/my/file/something.js"
url:
方案将自动解析 something.js
资产,并将其添加到构建包的 web_accessible_resources
声明中。上述 myFile
变量将是一个包含资产 URL 的字符串:
> console.log(myFile)
chrome-extension://<your chrome ext id>/something.eb20bc99.js?1656000646313
> console.log(myFile.split("/").pop().split("?")[0])
something.eb20bc99.js
或者,你可以使用 data-base64
或 data-text
方案将资产导入并嵌入到代码中。对于小型资产,这些方案应该很好用。
请参阅此 关于 ~
导入解析的说明