框架
内容脚本

内容脚本

内容脚本在网页的 隔离世界 中运行。这允许来自各种扩展的多个内容脚本共存,而不会相互冲突,并且与页面的 JavaScript 保持隔离。

.ts 结尾的脚本不会捆绑前端运行时(react/vue/svelte),也不会被视为 UI 脚本,而以 .tsx.vue.svelte 结尾的脚本则会被视为 UI 脚本。

使用场景:

添加单个内容脚本

🚨

由于 Plasmo 的默认 TypeScript 配置将所有源文件视为模块,如果你的代码中没有任何导入或导出,则需要在文件开头添加 export {} 行。(当你创建第一个内容脚本时会看到此警告!)

创建一个 content.ts 文件,导出一个空对象并开始编写代码!

content.ts
export {}
console.log(
  "你可能会发现,拥有并不是一件像渴望那样令人愉悦的事情。这并不合逻辑,但通常是真实的。"
)

重新加载你的扩展程序,打开一个网页,然后打开其检查器:

content-script-spock-quote

请参阅 with-content-script (opens in a new tab) 获取完整示例。

添加多个内容脚本

为多个内容脚本创建一个 contents 目录,并将你的内容脚本添加到其中。确保它们的名字描述了它们的功能!

请参阅 with-many-content-scripts (opens in a new tab) 获取示例。

配置

有时,你希望在某些页面上运行内容脚本。你可以通过从内容脚本中导出配置对象来提供自定义内容脚本配置:

content.ts
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 属性:

content.ts
import type { PlasmoCSConfig } from "plasmo"
 
export const config: PlasmoCSConfig = {
  matches: ["<all_urls>"],
  world: "MAIN"
}

上述脚本将被注入到主世界。

要手动注入主世界脚本,请使用 chrome.scripting.executeScript API。首先,在 package.json 的 'manifest.permissions' 数组 中手动添加脚本权限:

package.json
{
  ...
  "manifest" : {
    "permissions": ["scripting"]
  }
}

然后,通过调用 chrome.scripting.executeScript 将内容脚本注入到主世界:

background.ts
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-base64data-text 方案将资产导入并嵌入到代码中。对于小型资产,这些方案应该很好用。