Skip to Content
LaunchExt | Chrome Extension Dev Platform (Next.js + Plasmo) 🚀 Read more → 
BlogPlasmo Content Script Independent Configuration Mechanism Explained

Plasmo Content Script Independent Configuration Mechanism Explained

While working on Chrome extensions, I discovered a particularly useful feature of the Plasmo framework: every file in the contents directory can have its own independent PlasmoCSConfig, and they don’t interfere with each other at all.

Why Independent Configuration Matters

In real-world projects, we often need to write specialized content scripts for different pages or functionalities. For example:

  • Some scripts only need to run on specific domains
  • Some need to execute at different stages of page loading
  • Some need to inject UI components, while others only handle data processing

If all scripts shared the same configuration, configuration conflicts would be common. Plasmo’s design elegantly solves this problem.

Practical Applications of Independent Configuration

Domain-Specific Scripts

// contents/vulcan.ts - runs only on specific domains export const config: PlasmoCSConfig = { matches: ["https://vulcan.plasmo.com/*", "https://www.nowarpls.org/*"] } // contents/nested/index.tsx - runs on a different domain export const config: PlasmoCSConfig = { matches: ["https://itero.plasmo.com/*"] }

Different Execution Timings

// contents/content-isolated.ts - runs when page is idle export const config: PlasmoCSConfig = { matches: ["https://www.plasmo.com/*"], run_at: "document_idle" } // contents/relay.ts - runs immediately at document start export const config: PlasmoCSConfig = { matches: ["https://www.plasmo.com/*"], run_at: "document_start" }

Special Execution Environments

// contents/plasmo-main.ts - runs in main world export const config: PlasmoCSConfig = { matches: ["https://www.plasmo.com/*"], world: "MAIN", run_at: "document_start" }

UI Component Injection Scripts

// contents/plasmo-overlay.tsx - Overlay component with styles export const config: PlasmoCSConfig = { matches: ["https://www.plasmo.com/*"], css: ["font.css"] } // contents/plasmo-inline.tsx - Simple inline component export const config: PlasmoCSConfig = { matches: ["https://www.plasmo.com/*"] }

Technical Implementation Details

PlasmoCSConfig Type Definition

PlasmoCSConfig is essentially a wrapper around the ManifestContentScript type, but excludes the js field since Plasmo automatically handles JavaScript file paths:

export type PlasmoCSConfig = Omit<Partial<ManifestContentScript>, "js">

Configuration Isolation Mechanism

Plasmo implements configuration isolation through its manifest factory system. Each content script is handled independently via the toggleContentScript method:

  1. Extract configuration metadata: const metadata = await extractContentScriptConfig(path)
  2. Apply independent configuration: Each script’s configuration is processed separately
  3. Store in Map: this.contentScriptMap.set(path, contentScript)

The key insight is that configurations are stored in a Map using file paths as keys, ensuring complete isolation for each script’s configuration.

Final Merging Process

When generating the manifest, all independent configurations are merged into the content_scripts array:

base.content_scripts = [ ...Array.from(this.contentScriptMap.values()).filter( (s) => s.world !== "MAIN" ), ...(overrideContentScripts! || []) ]

Practical Recommendations

Based on my experience, this independent configuration design offers several clear benefits:

1. Better Code Organization

Each functional module has its own configuration, making it easy to locate and modify.

2. Avoid Configuration Conflicts

Different scripts can have different matches, run_at, and other configurations without interfering with each other.

3. Enhanced Team Collaboration

In multi-developer environments, each developer can independently configure their scripts, reducing merge conflicts.

4. Flexible Deployment Strategies

You can enable or disable specific content scripts as needed.

Frequently Asked Questions

Q: What happens if multiple scripts configure the same matches?

A: No problem at all! Each script will run independently on matching pages without interference.

Q: How are CSS files in the configuration handled?

A: Plasmo automatically resolves relative paths and correctly associates CSS files with their corresponding content scripts.

Q: What’s special about main world scripts?

A: Main world scripts (world: "MAIN") currently require special handling and are temporarily filtered out during final merging, awaiting Chrome’s native support.

Conclusion

Plasmo’s modular design is genuinely practical, making content script management straightforward and clear. Each script can focus on its specific functionality with clean, independent configurations, significantly improving development efficiency and code maintainability.

If you’re also using Plasmo for Chrome extension development, I strongly recommend leveraging this feature to organize your content scripts effectively. Feel free to reach out if you have any questions or want to discuss further!

Last updated on