crxjs / chrome-extension-tools

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

Content Script Delay #391

Open thyngster opened 2 years ago

thyngster commented 2 years ago

Build tool

Vite

Where do you see the problem?

Describe the bug

Because of the content loader and the async stuff, the content script injected gets delayed a lot. For my testing, I'm running a performance.now() from the contents script and also from a script injected from "registerContentScripts"

I ran a batch of 5 page loads:

67.20ms >> 182.00ms 52.40ms >> 154.29ms 48.00ms >> 143.59ms 47.20ms >> 136.50ms 83.00ms >> 223.00ms

This made me implement a messages queue from the inspected site, in order to be able to pass the messages back when the content is loaded.

If I put the code directly in the content script it gets injected even before the one coming from the "registerContentScripts" . I only use the content script to pass back the messages from the page to the background/panel page.

Note: Even removing the async stuff and leaving the import() statement, makes a delay, which may not be a big issue is most sites at all, but still annoying.

At the moment I'm not sure if this is a bug or some expected behavior by crxjs.

Reproduction

Just try a console.log(performance.now()) using the tool generated content.js vs running it directly on the content.js

Logs

No response

System Info

Windows, Chrome(102) , Chrome Canary (104)

Severity

annoyance

jacksteamdev commented 2 years ago

Because of the content loader and the async stuff

Are you talking about this?

https://github.com/crxjs/chrome-extension-tools/blob/a9baf3b3fb5887f8f41c203f16398e9896583309/packages/vite-plugin/src/client/iife/content-dev-loader.ts#L4-L10

Content scripts are tricky b/c they load from the file system and don't support ES modules (except by dynamic import). CRXJS uses dynamic imports in the async loader b/c Vite's HMR implementation uses ES modules to accept updates.

The async loader adds support for the Vite HMR Client, which must load before the content script. Without it, the content script won't accept updates.

If you can provide a minimum reproduction, maybe I can offer some better help. 🙏

thyngster commented 2 years ago

Yep, talking about that, So what I'm doing is, I'm injecting an script like this:

chrome.scripting.registerContentScripts([
  {
    id: "loaddelaytest",
    js: ["/src/libs/inject.js"],
    matches: ["*://*/*"],
    persistAcrossSessions: true,
    runAt: "document_start",
    world: "MAIN",
  },
]);

This injected script passes some data to the content_script and this last one relays it to the background. The problem issues is that while the inject.js gets loaded in 50ms , it takes the content_script 250ms , meaning that all the messages happening before that point are lost.

On my MV2 version, I knew that content_script was injected really quick into the site, so that 250 were not making much sense. Then I just tested removing all the imports logic from the generated script and just putting the code into the file, and then it was running even before the code injected from the content script. So my guess that all these async and imports are delaying the content script loading x5 ( on my tests )

I'll try to setup some demo repo which I think it could help.

thyngster commented 2 years ago

There it goes: https://github.com/thyngster/crxjs-delay-test

There's an output demo screenshot at: https://github.com/thyngster/crxjs-delay-test/blob/main/output_demo.jpg

If you remove all the HRM async imports from the content and just leave the console.log on it, you'll see that then it fired always before.

The delay depends on the site, it feels like Chrome doesn't have a separate async queue for the assets loaded on the extension and that's its shared with the main tab, so depending on how the site loads it will take more or less time.

ksmsk commented 1 year ago

at the moment "run_at": "document_start" kinda useless since dynamic importing modules will take time anyway. it's ok to have while in dev mode but it would be nice having es5 output option on build mode.

bruceeewong commented 1 year ago

Does this issue get any update? I am a wallet extension developer who use this vite plugin to build. Also experiencing unexpected behaviors with this extra async import logic. That is, even I specify "run_at": "document_start", the content script is injected after the host website loads, causing dapps cannot detect our wallet, which is a disaster to user experience... I wonder if there is a mode that straightly specify our own content script without the async wrapping? Thanks!

sapondanaisriwan commented 5 months ago

any update on this issue?

markkkkas commented 4 months ago

im experiencing this issue as well, any input from maintainers would be awesome 🙏