Content Scripts – Plasmo

Content scripts run in the context of web pages in an isolated world. This allows multiple content scripts from various extensions to coexist without conflicting with each other's execution and to stay isolated from the page's JavaScript.

A script that ends with .ts will not have front-end runtime (react/vue/svelte) bundled with it and won't be treated as a ui script, while a script that ends in .tsx, .vue or .svelte, will be.

Use cases:

Adding a single content script

Create a content.ts file, export an empty object and hack away!

Reload your extension, open a web page, then open its inspector:

content-script-spock-quote

See with-content-script (opens in a new tab) for a full example.

Adding multiple content scripts

Create a contents directory for multiple content scripts, and add your content scripts there. Make sure their names describe what they do!

See with-many-content-scripts (opens in a new tab) for an example.

Config

Sometimes, you'll want to run a content script on certain pages. You can provide a custom content script configuration by exporting a config object from your content script:

Working with this configuration object is a breeze thanks to the exported PlasmoCSConfig type 🥳.

To learn more about the config and each property, check out Chrome's official documentation (opens in a new tab).

Injecting into the main world

To modify the window object from your content script, you must inject code into the "main world."

Starting from Plasmo v0.65.0, Plasmo content script may specify a world property within the config:

The above script will be injected into the main world.

To manually inject a main world script, use the chrome.scripting.executeScript API. First, manually add the scripting permission in your package.json's 'manifest.permissions' array:

Then, inject your content script into the main world by calling chrome.scripting.executeScript from your background service worker:

For the func key, you can pass in a TS function from your project. It will be transpiled into JS when your extension bundles. You may also use the files key to inject a file from the root of the built bundle.

See with-main-world (opens in a new tab) for an example.

Fetching external API and CORS

Because content scripts run within the context of a web page, they are subject to the same-origin policy. To mitigate CORS restrictions, you can use the Plasmo Messaging API to proxy the request via your background service worker.

Importing resources

To import external assets into your content script, you can use the url: scheme:

The url: scheme will automatically resolve the something.js asset and add it to the web_accessible_resources declaration in the built bundle. The above myFile variable will be a string containing the URL to the asset:

Alternatively, you can use the data-base64 or the data-text scheme to import and embed the asset directly into your code. For small assets, these schemes should work well.

Sandbox PagesContent Scripts UI