Special import syntax and type definitions for content scripts, enabling different script formats and execution environments with HMR support. Provides seamless integration between modern development workflows and Chrome extension runtime requirements.
Special import suffixes that transform script files for different Chrome extension execution contexts.
/**
* Default script import - alias for ?script&loader
* ESM format with dynamic import loader and HMR support
* Use with Chrome Scripting API in background scripts or extension pages
*/
declare module '*?script' {
const fileName: string;
export default fileName;
}
/**
* Explicit loader format
* ESM format loaded via dynamic import script with HMR support
* Exports the filename of the loader script for Chrome Scripting API
*/
declare module '*?script&loader' {
const fileName: string;
export default fileName;
}
/**
* IIFE (Immediately Invoked Function Expression) format
* Self-contained script for content scripts with opaque origins
* No HMR support but guaranteed isolated execution
*/
declare module '*?script&iife' {
const fileName: string;
export default fileName;
}
/**
* Pure ES module format
* No loader wrapper, no HMR support
* For injection into main world or when framework HMR is not needed
*/
declare module '*?script&module' {
const fileName: string;
export default fileName;
}Usage Examples:
// In background script or extension page
import contentScript from "./content.ts?script";
import contentScriptLoader from "./content.ts?script&loader";
import contentScriptIIFE from "./content.ts?script&iife";
import contentScriptModule from "./content.ts?script&module";
// Inject using Chrome Scripting API
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: [contentScript], // Uses the generated filename
});
// Inject into main world (requires ?script&module)
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: [contentScriptModule],
world: "MAIN",
});Interface for content scripts to integrate with the CRXJS execution lifecycle and performance monitoring.
declare namespace ContentScriptAPI {
/**
* Performance metrics for content script execution
*/
interface ExecuteFnOptions {
perf: {
/** Time taken to inject the script (milliseconds) */
injectTime: number;
/** Time taken to load the script (milliseconds) */
loadTime: number;
};
}
/**
* Optional execution callback function
* Called when the content script is executed with performance metrics
*/
interface ExecuteFn {
(options: ExecuteFnOptions): void;
}
/**
* Module exports interface for content scripts
* Content scripts can export an onExecute function to receive execution callbacks
*/
interface ModuleExports {
/** Optional callback executed when the script runs */
onExecute?: ExecuteFn;
}
}Usage Examples:
// In content script file (content.ts)
/// <reference types="@crxjs/vite-plugin/client" />
// Export execution callback to receive performance metrics
export const onExecute: ContentScriptAPI.ExecuteFn = (options) => {
console.log(`Content script injected in ${options.perf.injectTime}ms`);
console.log(`Content script loaded in ${options.perf.loadTime}ms`);
// Initialize content script functionality
initializeContentScript();
};
function initializeContentScript() {
// Content script implementation
console.log("Content script is running!");
// Access to all standard web APIs
document.addEventListener('DOMContentLoaded', () => {
// DOM manipulation
});
// Chrome extension APIs (in isolated world)
chrome.runtime.sendMessage({ type: 'content-script-ready' });
}
// Alternative: Direct execution without callback
console.log("Content script executing directly");Type definitions for client-side module imports and dynamic resources.
/**
* Client code modules - used internally by CRXJS
* Exports raw code as string for injection
*/
declare module 'client/*' {
const code: string;
export default code;
}
/**
* Dynamic localhost modules for development
* Supports Vite dev server integration
*/
declare module 'http://localhost:*/*' {
const module: any;
export = module;
}
/**
* Dynamic path-based modules
* Supports runtime module resolution
*/
declare module '*/%PATH%' {
const module: any;
export = module;
}?script (Default / Loader Format):
import contentScript from "./react-content.tsx?script";
// Generates a loader that dynamically imports the actual content script
// Supports hot reloading and framework-specific HMR?script&iife Format:
import contentScript from "./simple-content.ts?script&iife";
// Generates an IIFE that executes immediately
// No HMR support but guaranteed to work in all contexts?script&module Format:
import mainWorldScript from "./page-script.ts?script&module";
chrome.scripting.executeScript({
target: { tabId },
files: [mainWorldScript],
world: "MAIN", // Inject into page's main world
});Development Mode:
Production Mode:
Multi-Script Coordination:
// Background script coordinating multiple content scripts
import mainScript from "./main-content.ts?script";
import helperScript from "./helper.ts?script&iife";
async function injectContentScripts(tabId: number) {
// Inject helper script first (IIFE for immediate execution)
await chrome.scripting.executeScript({
target: { tabId },
files: [helperScript],
});
// Then inject main script (with HMR and dependencies)
await chrome.scripting.executeScript({
target: { tabId },
files: [mainScript],
});
}Conditional Script Loading:
// Load different scripts based on page context
import devScript from "./dev-content.ts?script";
import prodScript from "./prod-content.ts?script&iife";
const scriptToInject = process.env.NODE_ENV === 'development'
? devScript
: prodScript;
chrome.scripting.executeScript({
target: { tabId },
files: [scriptToInject],
});Performance Monitoring:
// Content script with performance tracking
export const onExecute: ContentScriptAPI.ExecuteFn = (options) => {
// Track performance metrics
const metrics = {
injectTime: options.perf.injectTime,
loadTime: options.perf.loadTime,
startTime: Date.now(),
};
// Send metrics to background script
chrome.runtime.sendMessage({
type: 'performance-metrics',
metrics,
});
// Continue with script initialization
initializeScript();
};The client API provides full TypeScript support with strict type checking.
Type-Safe Content Scripts:
// Type-safe content script with proper interfaces
/// <reference types="@crxjs/vite-plugin/client" />
interface ContentScriptState {
initialized: boolean;
features: string[];
}
const state: ContentScriptState = {
initialized: false,
features: [],
};
export const onExecute: ContentScriptAPI.ExecuteFn = (options) => {
// Type-safe access to performance metrics
const { injectTime, loadTime } = options.perf;
if (injectTime > 100) {
console.warn(`Slow injection time: ${injectTime}ms`);
}
state.initialized = true;
state.features.push('performance-monitoring');
};Environment-Specific Types:
// Different types for different execution contexts
interface MainWorldAPI {
// APIs available in main world
pageFunction: () => void;
}
interface ContentScriptAPI {
// APIs available in content script world
chromeExtensionAPI: typeof chrome;
}
// Use appropriate types based on script format
import mainWorldScript from "./main.ts?script&module"; // MainWorldAPI
import contentScript from "./content.ts?script"; // ContentScriptAPI