Content Scripts
CRXJS provides content scripts with Vite HMR, so updates don't always require a full host page reload. In addition, frameworks like React and Vue work in content scripts the same as HTML pages.
The host page of a content script is the website where the content script is running.
Static Assets
Feel free to import static assets! CRXJS automatically declares imported content
script dependencies as web_accessible_resources
in the manifest.
Use the extension URL
Content scripts share the origin of the host page, so convert imported static assets to the extension origin using the Chrome API.
import logo from './logo.png'
const url = chrome.runtime.getURL(logo)
HTML in content scripts
It is possible to inject an extension page into a host page using an iframe. The
host page CSP does not affect the injected iframe even if the host page
specifies the frame-src
policy.
An injected extension page loads inside a cross-origin iframe, so it does not have access to the host page DOM like a content script.
const src = chrome.runtime.getURL('pages/iframe.html')
const iframe = new DOMParser().parseFromString(
`<iframe class="crx" src="${src}"></iframe>`,
).body.firstElementChild
document.body.append(iframe)
Injected extension pages do have access to the full Chrome API, however.
If you load an HTML file from a content script, you need to declare the file as a web-accessible resource.
{
"web_accessible_resources": [
{
"resources": ["pages/iframe.html"],
"matches": ["https://*.google.com/*"]
}
]
}
You will also need to add the HTML file to your Vite config under
build.rollupOptions.input
.
export default defineConfig({
build: {
rollupOptions: {
input: {
welcome: 'pages/iframe.html',
},
},
},
})
Imported HTML
If you need to render complex HTML in a content script without a framework, an
HTML file can serve as a static fragment by importing it as text using the
?raw
query. This technique does not require the file to be web-accessible, and
you don't need to declare it in the Vite config.
import html from './root.html?raw'
const iframe = new DOMParser().parseFromString(html).body.firstElementChild
iframe.src = chrome.runtime.getURL('pages/iframe.html')
document.body.append(iframe)
Importing an HTML file as text lets you take advantage of IDE language services
for HTML files. Depending on your HTML, this technique may be more concise than
using document.createElement()
.