crxjs / chrome-extension-tools

Bundling Chrome Extensions can be pretty complex. It doesn't have to be.
https://crxjs.dev/vite-plugin
2.75k stars 182 forks source link

Assets loaded in content script result in 404 #842

Open hdodov opened 9 months ago

hdodov commented 9 months ago

Build tool

Vite

Where do you see the problem?

Describe the bug

I have a simple content script that imports CSS with fonts:

manifest.json:

{
    "content_scripts": [
        {
            "js": ["src/content.tsx"],
            "matches": ["file:///*", "http://*/*", "https://*/*"]
        }
    ]
}

content.tsx:

import "./index.css";
// Other stuff...

index.css:

@import "@fontsource/inter/400.css";
/* Other stuff... */

I do the same in the extension popup and it works perfectly there. However, in the content script, it results in the extension attempting to load the resources from the visited website, and you obviously get a 404:

https://example.com/assets/inter-latin-400-normal-2301bb03.woff2 → 404

This problem has been raised in Stack Overflow and the solution is to use a special string in the CSS resource path, as explained in the Chrome docs:

body {
    background-image: url('chrome-extension://__MSG_@@extension_id__/background.png');
}

And indeed, if I build my extension, go to the generated CSS, and manually prepend chrome-extension://__MSG_@@extension_id__, everything starts working. In other words, this:

@font-face {
    src: url(/assets/inter-latin-400-normal-2301bb03.woff2) format("woff2");
}

…has to turn to this:

@font-face {
    src: url(chrome-extension://__MSG_@@extension_id__/assets/inter-latin-400-normal-2301bb03.woff2) format("woff2");
}

Reproduction

Create a content script and try to import any CSS asset.

Logs

No response

System Info

System:
    OS: Windows 11 10.0.22621
    CPU: (12) x64 12th Gen Intel(R) Core(TM) i5-12400F
    Memory: 6.68 GB / 15.82 GB
  Binaries:
    Node: 20.10.0 - ~\AppData\Local\Volta\tools\image\node\20.10.0\node.EXE
    Yarn: 1.22.19 - ~\AppData\Local\Volta\tools\image\yarn\1.22.19\bin\yarn.CMD
    npm: 10.2.3 - ~\AppData\Local\Volta\tools\image\node\20.10.0\npm.CMD
  Browsers:
    Edge: Chromium (120.0.2210.61)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    @crxjs/vite-plugin: ^2.0.0-beta.21 => 2.0.0-beta.21 
    vite: ^4.3.9 => 4.5.0 


### Severity

annoyance
hdodov commented 9 months ago

In addition, chrome-extension://__MSG_@@extension_id__ appears to resolve correctly in popup scripts as well. If I add it in the same CSS file that is loaded both in the popup and the content script — it works in both places.

Maybe one possible solution is to just always prepend chrome-extension://__MSG_@@extension_id__, regardless of the script's location (popup or content)?

hdodov commented 9 months ago

As @KTibow suggested in the Vite Discord server where I asked for help, the experimental renderBuiltUrl option can be used:

vite.config.ts:

export default defineConfig({
    plugins: [solidPlugin(), crx({ manifest })],
    experimental: {
        renderBuiltUrl(filename, { hostType }) {
            if (hostType === "css") {
                return `chrome-extension://__MSG_@@extension_id__/${filename}`;
            }
        },
    },
});

It prepends the string to the output asset URLs and works perfectly. Still, in my opinion, it'd be great if CRXJS uses this internally, so end-users don't have to face this issue.