crxjs / chrome-extension-tools

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

Issue with loading regular script from /public #441

Open Andarist opened 2 years ago

Andarist commented 2 years ago

Build tool

Vite

Where do you see the problem?

Describe the bug

I need to load an external UMD script for a devtool's panel. Ideally, a blocking one because it creates a global variable that I need to use in the app.

My intuition was to just put it in the /public directory and reference it from panel.html. While this has worked (mostly?):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <script src="../public/elk-0.7.1.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/panel.tsx"></script>
  </body>
</html>

I got warnings from Vite (?) that I should reference files from /public using the root and that I should use /elk-0.7.1.js. So I've followed the advice:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <script src="/elk-0.7.1.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/panel.tsx"></script>
  </body>
</html>

Unfortunately this change stopped loading the referenced script so I've kept digging and I've found out that this got "processed" into this:

import { injectQuery as __vite__injectQuery } from "/@vite/client";
import RefreshRuntime from "/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true

try {
  for (const p of JSON.parse("[\"/src/elk-0.7.1.js\",\"/src/panel.tsx\"]")) {
    const url = new URL(p, "https://stub");
    url.searchParams.set("t", Date.now().toString());
    const req = url.pathname + url.search;
    await import(
      /* @vite-ignore */
      __vite__injectQuery(req, 'import'));
  }
} catch (error) {
  console.error(error);
}

As we may notice - both scripts include /src/ in the path but that was never the intention here. Luckily, I will be able to easily fix this. However, I did not see any error about it whatsoever - despite that it seems that there is a console.error here, associated with this request.

Reproduction

I could try to minimize my repro case later but I hope that the description of the issue is somewhat clear.

Logs

No response

System Info

System:
    OS: macOS 12.3
    CPU: (10) x64 Apple M1 Pro
    Memory: 40.38 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 12.22.11 - ~/Library/Caches/fnm_multishells/18695_1655822009676/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 6.14.16 - ~/Library/Caches/fnm_multishells/18695_1655822009676/bin/npm
    Watchman: 2022.06.06.00 - /opt/homebrew/bin/watchman
  Browsers:
    Brave Browser: 95.1.31.88
    Chrome: 99.0.4844.51
    Chrome Canary: 101.0.4945.0
    Firefox Nightly: 79.0a1
    Safari: 15.4
    Safari Technology Preview: 11.2

Severity

annoyance

jacksteamdev commented 2 years ago

We need better support for unbundled scripts. I like the idea of putting them in public, seems like a reasonable approach is to check if a script in the manifest or an HTML file is in public; we can simply copy these over.