crxjs / chrome-extension-tools

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

CSP Issue on Chrome 130+ #918

Closed sebastienfontaine closed 3 weeks ago

sebastienfontaine commented 2 months ago

Build tool

Vite

Where do you see the problem?

Describe the bug

When using Chrome version 130 and above, a browser error occurs when loading the content.js script.

content.ts-loader-DE-4zCml.js:

Refused to load the script 'chrome-extension://65fbf486-37dc-4a71-a17e-a567b680778b/assets/content.ts-B_w-r5D-.js' because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:*". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
TypeError: Failed to fetch dynamically imported module: chrome-extension://65fbf486-37dc-4a71-a17e-a567b680778b/assets/content.ts-B_w-r5D-.js
image

Reproduction

Clone this repository: https://github.com/furybee/crxjs-extension, or create a new repository with a content.js file as content_scripts.

Run the following command:

npm run build

Import the extension into Chrome 130+ (Canary Builds): https://www.google.com/chrome/canary/

Check the console to see the error.

Logs

No response

System Info

System:
    OS: macOS 14.5
    CPU: (10) arm64 Apple M2 Pro
    Memory: 77.75 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.12.2 - ~/.nvm/versions/node/v20.12.2/bin/node
    Yarn: 1.22.22 - ~/.yarn/bin/yarn
    npm: 10.5.0 - ~/.nvm/versions/node/v20.12.2/bin/npm
    Watchman: 2024.05.06.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 128.0.6613.138
    Chrome Canary: 130.0.6719.0
    Edge: 128.0.2739.79
    Safari: 17.5
  npmPackages:
    @crxjs/vite-plugin: ^2.0.0-beta.25 => 2.0.0-beta.25 
    vite: ^5.4.1 => 5.4.5

manifest.json

{
  "manifest_version": 3,
  "name": "CRXJS Vue Vite Example",
  "version": "1.0.0",
  "action": { "default_popup": "index.html" },
  "content_scripts": [{
    "matches": [ "*://*/*" ],
    "js": [
      "src/content.ts"
    ]
  }]
}

Severity

🚨 blocking all usage of crxjs 🚨

trungpv1601 commented 2 months ago

Same 🚨

My solution for build production

remove chrome.runtime.getURL in content script

(function () {
  'use strict';

  (async () => {
    await import("./chunk-b674a675.js");
  })().catch(console.error);

})();
matteing commented 2 months ago

Having the same issue as well.,

pnd280 commented 2 months ago

I worked around this by setting use_dynamic_url to false. But even if you don't use use_dynamic_url in manifest.ts, the compiled manifest.json will still have it, and crxjs doesn't have the option to disable it. So one might try to write a Vite plugin to forcefully remove them from the compiled manifest.json.

pnd280 commented 2 months ago

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

trungpv1601 commented 2 months ago

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

Same idea with you but not found the best one 👨‍💻

Firefox does not support MV3 yet. So for me, only focus on Chrome.

Still using this hot-fix for v130.

https://github.com/crxjs/chrome-extension-tools/issues/918#issuecomment-2351900637

pietrofxq commented 1 month ago

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

Same idea with you but not found the best one 👨‍💻

Firefox does not support MV3 yet. So for me, only focus on Chrome.

Still using this hot-fix for v130.

#918 (comment)

I think it supports it now. I've ported my MV3 extension to firefox with almost no changes.

trungpv1601 commented 1 month ago

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

Same idea with you but not found the best one 👨‍💻 Firefox does not support MV3 yet. So for me, only focus on Chrome. Still using this hot-fix for v130. #918 (comment)

I think it supports it now. I've ported my MV3 extension to firefox with almost no changes.

Nice 😊. Thank you for your information. I will take a look

scisley commented 1 month ago

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (https://github.com/crxjs/chrome-extension-tools/issues/918#issuecomment-2351900637) will work for me. I need to call chrome.runtime.getURL in my content script.

trungpv1601 commented 1 month ago

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

Can you show example in your code? I will help

pnd280 commented 1 month ago

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

here's how I worked around this issue https://github.com/pnd280/complexity/issues/7

trungpv1601 commented 1 month ago

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

More attachment on how to hot-fix my extensions

After building, you should edit it like this. I hope it helps.

CleanShot 2024-09-26 at 09 27 20@2x

scisley commented 1 month ago

@trungpv1601, @pnd280 - thank you both! The extra details allowed me to piece together a solution.

Toumash commented 1 month ago

Are we able prepare a PR for that change or more work is needed?

trungpv1601 commented 1 month ago

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something? I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

here's how I worked around this issue pnd280/complexity#7

I think this is the best solution for now. It works well for Chrome and Firefox builds.

Thank you @pnd280 🙏

Lonolf commented 1 month ago

Same problem, we use our extension with InboxSDK to insert some buttons in the gmail page. I was able to temporary fix the extension by changing the "use_dynamic_url" flag in the builded manifest to false, but we hope in a more stable solution

quentin-decre commented 1 month ago

Can we expect a PR to handle that ? Is someone already on that ?

salmin89 commented 1 month ago

is this an issue with chrome that needs to be reported? how come use_dynamic_url became a problem all of a sudden?

pietrofxq commented 1 month ago

is this an issue with chrome that needs to be reported? how come use_dynamic_url became a problem all of a sudden?

Looks like support for that property was actually just added in Chrome 130:

https://developer.chrome.com/blog/extension-news-october-2024

Starting in Chrome 130, we will enable support for the use_dynamic_url property on entries under the web_accessible_resources key in the manifest.

I don't know why CRXJS marks it as true in the final manifest.json, looks like a simple PR that removes it would be enough?

pietrofxq commented 1 month ago

FIX WITH PATCH-PACKAGE (DEV AND BUILD)

Add patch-package:

yarn add --dev patch-package

Change the use_dynamic_url flag to false in node_modules/@crxjs/vite-plugin/dist/index.mjs in lines 1842 and 1924:

use_dynamic_url: false

Run patch-package:

npx patch-package @crxjs/vite-plugin

Add patch-package to postinstall script in package.json:

"postinstall": "patch-package"

This fixes the issue at the source so it will work correctly in both dev and prod builds

PS: If you are using yarn 3, this can be fixed with yarn patch instead of patch-package

FIX WITH NODEJS SCRIPT (BUILD ONLY)

create a js script, e.g set-dynamic-url.cjs. Update the path of manifest if needed to reflect your folder structure

const fs = require('node:fs')
const path = require('node:path')
const manifest = require('../dist/manifest.json')

const webAccessibleResources = manifest.web_accessible_resources

const updatedWebAccessibleResources = webAccessibleResources.map(resource => {
  if (resource.use_dynamic_url) {
    return {
      ...resource,
      use_dynamic_url: false,
    }
  }
  return resource
})

manifest.web_accessible_resources = updatedWebAccessibleResources

const json = JSON.stringify(manifest, null, 2)
fs.writeFileSync(path.resolve(__dirname, '../dist/manifest.json'), json, 'utf8')

Add it to postbuild under package.json scripts:

"build": "vite build",
"postbuild": "node ./scripts/set-dynamic-url.cjs",

Now the manifest.json in the dist folder will be automatically patched when running yarn build

scarletczen commented 1 month ago

For now, the production build works using @pnd280 's solution (thank you), dev mode is still an issue, did anyone get it to work yet?

salmin89 commented 1 month ago

I threw together this hack plugin that uses fs.watchFile to update manifest.json in dev mode (works normally for build) I'm no expert on vite-plugins so feel free to modify or share something more robust.

import path from 'node:path';
import fs from 'fs';
import { PluginOption } from 'vite';
import { ManifestV3Export } from '@crxjs/vite-plugin';

const manifestPath = path.resolve('dist/manifest.json'); // your manifest output location

export function updateManifestPlugin(): PluginOption {
  return {
    name: 'update-manifest-plugin',
    enforce: 'post',
    closeBundle() {
      forceDisableUseDynamicUrl();
    },

    configureServer(server) {
      server.httpServer?.once('listening', () => {
        const updated = forceDisableUseDynamicUrl();
        if (updated) {
          server.ws.send({ type: 'full-reload' });
          console.log('** updated **');
        }

        fs.watchFile(manifestPath, (data) => {
          console.log('** watchFile ** ');
          const manifestContents = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
          if (manifestContents.web_accessible_resources.some((resource: any) => resource.use_dynamic_url)) {
            const updated = forceDisableUseDynamicUrl();
            if (updated) {
              server.ws.send({ type: 'full-reload' });
              console.log('** updated **');
            }
          }
        });
      });
    },

    writeBundle() {
      console.log('### writeBundle ##');
      forceDisableUseDynamicUrl();
    },
  };
}

function forceDisableUseDynamicUrl() {
  if (!fs.existsSync(manifestPath)) {
    return false;
  }

  const manifestContents = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as Awaited<ManifestV3Export>;

  if (typeof manifestContents === 'function' || !manifestContents.web_accessible_resources) return false;
  if (manifestContents.web_accessible_resources.every((resource) => !resource.use_dynamic_url)) return false;

  manifestContents.web_accessible_resources.forEach((resource) => {
    if (resource.use_dynamic_url) resource.use_dynamic_url = false;
  });

  fs.writeFileSync(manifestPath, JSON.stringify(manifestContents, null, 2));
  return true;
}

use normally in vite.config.ts

    plugins: [react(), crx({ manifest }), updateManifestPlugin()],
pietrofxq commented 1 month ago

my solution above with patch-package fixes it for dev and build modes

salmin89 commented 1 month ago

my solution above with patch-package fixes it for dev and build modes

I'm not using yarn tho

pietrofxq commented 1 month ago

my solution above with patch-package fixes it for dev and build modes

I'm not using yarn tho

yarn is not required, patch-package is a npm package. Just change it to

npm install --save-dev patch-package
salmin89 commented 1 month ago

I will test that approach out. Thanks!

xc2 commented 1 month ago

An example to patch it with pnpm: https://github.com/xc2/follow-it-later/pull/22

salmin89 commented 1 month ago

The chromium team were aware of this issue (see comment https://issues.chromium.org/issues/363027634#comment4)

And someone even mentioned vite-plugin-web-extension being affected which seems to have been patched quickly by the author.

CrxJs seems unmaintained. No update since 2022 (which is a shame, since it's awesome) https://github.com/crxjs/chrome-extension-tools/discussions/872


Change the use_dynamic_url flag to false in node_modules/@crxjs/vite-plugin/dist/index.mjs in lines 1842 and 1924:

@pietrofxq if you want to make a PR with the fix above, we can all thumbs up it. If you aren't going to, let us know and I can do it.

pietrofxq commented 1 month ago

Last version was released on July, but it was a beta version of version 2 (which is the one I am using): https://github.com/crxjs/chrome-extension-tools/releases/tag/%40crxjs%2Fvite-plugin%402.0.0-beta.25

not sure who to ping about it. I can create a PR to change the default flag to false

pietrofxq commented 1 month ago

besides setting the default to false, I believe it should be also fixed to respect what is set on manifest.json. Looks like the value set there is completely ignored currently.

Toumash commented 1 month ago

Last version was released on July, but it was a beta version of version 2 (which is the one I am using): https://github.com/crxjs/chrome-extension-tools/releases/tag/%40crxjs%2Fvite-plugin%402.0.0-beta.25

not sure who to ping about it. I can create a PR to change the default flag to false

I guess lets ping jacksteamdev with the PR and he will wake up to merge it :D

salmin89 commented 1 month ago

besides setting the default to false, I believe it should be also fixed to respect what is set on manifest.json. Looks like the value set there is completely ignored currently.

That would be great as well.

We can ping jacksteamdev and AmySteam on the PR and hope for the best.

tommywalkie commented 1 month ago

I went on a similar plugin hack as @salmin89 but in my use-case, extension build steps are already ignored while in dev mode. That way, this plugin is all you need:

import fs from 'fs';
import type { ManifestV3Export } from '@crxjs/vite-plugin';

// ManifestV3 type is not exported the lib, but we can infer it
type ManifestV3 = Exclude<
  ManifestV3Export,
  Promise<any> | ((...args: any[]) => any)
>;

const patchDynamicUrlsPlugin = {
  name: 'patch-dynamic-urls-plugin',
  writeBundle() {
    const manifestPath = 'dist/manifest.json'; // Edit that part if your 'outDir' is different
    const manifestContent: ManifestV3 = JSON.parse(
      fs.readFileSync(manifestPath, 'utf8'),
    );

    if (manifestContent.web_accessible_resources) {
      manifestContent.web_accessible_resources =
        manifestContent.web_accessible_resources.map(resource => ({
          ...resource,
          use_dynamic_url: false,
        }));
    }

    fs.writeFileSync(manifestPath, JSON.stringify(manifestContent, null, 2));
  },
};

Then add it to your plugins among the ones that need to run when building extension.

plugins: [
  // ... other plugins
  ...(isExtensionBuild ? [crxjs(...), patchDynamicUrlsPlugin] : [])
]
ffaubert commented 1 month ago

patch-package didn't fully fix the situation for me. Instead used the code @salmin89 posted (thank you!!), but had issues with the manifest not always being written to disk before the code runs. I added some code to wait for the file. I am also a novice at vite plugins, but this got things working for me in build and dev modes, until the PR gets merged.

/* eslint-disable sonarjs/no-nested-functions */
import path from "node:path";
import fs from "node:fs";

import { waitForFile } from "@knowfun/utils-node";

const manifestPath = path.resolve("dist/manifest.json");

function updateManifestPlugin() {
    return {
        name: "update-manifest-plugin",
        enforce: "post",
        async closeBundle() {
            await waitForFile(manifestPath, 40, 500);
            forceDisableUseDynamicUrl();
        },

        configureServer(server) {
            server.httpServer?.once("listening", async () => {
                await waitForFile(manifestPath, 40, 500);
                const updated = forceDisableUseDynamicUrl();
                if (updated) {
                    server.ws.send({ type: "full-reload" });
                }

                fs.watchFile(manifestPath, (_data) => {
                    const manifestContents = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
                    if (manifestContents.web_accessible_resources.some((resource) => resource.use_dynamic_url)) {
                        // eslint-disable-next-line no-shadow
                        const updated = forceDisableUseDynamicUrl();
                        if (updated) {
                            server.ws.send({ type: "full-reload" });
                        }
                    }
                });
            });
        },

        async writeBundle() {
            await waitForFile(manifestPath, 40, 500);
            forceDisableUseDynamicUrl();
        },
    };
}

function forceDisableUseDynamicUrl() {
    if (!fs.existsSync(manifestPath)) {
        return false;
    }

    const manifestContents = JSON.parse(fs.readFileSync(manifestPath, "utf8"));

    if (typeof manifestContents === "function" || !manifestContents.web_accessible_resources) {
        return false;
    }
    if (manifestContents.web_accessible_resources.every((resource) => !resource.use_dynamic_url)) {
        return false;
    }

    manifestContents.web_accessible_resources.forEach((resource) => {
        if (resource.use_dynamic_url) {
            resource.use_dynamic_url = false;
        }
    });

    fs.writeFileSync(manifestPath, JSON.stringify(manifestContents, null, 2));
    return true;
}

export { updateManifestPlugin };

code for waitForFile and delay

const delay = (ms) => new Promise((res) => setTimeout(res, ms)); // eslint-disable-line no-promise-executor-return

async function waitForFile(filePath, maxAttempts = 10, interval = 1000) {
    let attempts = 0;
    let fileExists = fs.existsSync(filePath);

    while (!fileExists && attempts < maxAttempts) {
        await delay(interval);
        fileExists = fs.existsSync(filePath);
        attempts++;
    }

    return fileExists ? true : false;
}
salmin89 commented 1 month ago

@ffaubert in my code example I listen to all changes on manifest.json, but only update the file if there is any use_dynamic_url set to true. (to prevent an infinite watch loop).

The only issue with my code example would be that you might have to manually hit reload on the extension. I thought server.ws.send({ type: 'full-reload' }); does this but it didn't work for me. Manual reload once did. HMR and everything else works as normal.

But I do prefer @pietrofxq solution. How come it didn't work for you?

pietrofxq commented 1 month ago

I am also curious as to how patch-package did not fix it. Did you update the correct lines in index.mjs? I've updated two chrome extensions with this fix and they are all back working.

To check it works you can clean node_modules, run yarn (or npm install), run vite build and check that the generated manifest.json has use_dynamic_url: false under all entries in web_accessible_resources

saxoncameron commented 1 month ago

An example to patch it with pnpm: xc2/follow-it-later#22

+1 for patching the package directly, we did it using pnpm patch with a very similar/same patch diff as the above. Fixed the issue in dev mode, and in the final build. It is a very simple/small fix to this problem in terms of taking things into ones own hands (though ofc it would be nicer to have this fixed upstream).

We caught onto this issue late unfortunately. Last week a user reported to us that our extension had stopped working, and turns out their browser had been upgrade early to v130 which gave us the lead. Saw the CSP issue early-on in our content script execution, found a Reddit thread that basically brought us here, and then we did the pnpm patch straight away.

Unfortunately, even though we patched immediately, and submitted the patch for review last Monday, the Chrome Web store process was slower than it typically has been for us in the past, and it wasn't until Thursday that we managed to get the hotfix out to all users, which was about ~1.5d too late (v130 had started rolling out to all users). Had to do some damage control, an email blast, etc. Pity that hotfix release-timelines are at the mercy of a random review time 🥲

But what can you do. Our takeaway lesson was that we should be developing in Chrome Canary, so we'll be well aware in advance when/if an upcoming Chrome version is going to break things 😭

pietrofxq commented 1 month ago

An example to patch it with pnpm: xc2/follow-it-later#22

+1 for patching the package directly, we did it using pnpm patch with a very similar/same patch diff as the above. Fixed the issue in dev mode, and in the final build. It is a very simple/small fix to this problem in terms of taking things into ones own hands (though ofc it would be nicer to have this fixed upstream).

We caught onto this issue late unfortunately. Last week a user reported to us that our extension had stopped working, and turns out their browser had been upgrade early to v130 which gave us the lead. Saw the CSP issue early-on in our content script execution, found a Reddit thread that basically brought us here, and then we did the pnpm patch straight away.

Unfortunately, even though we patched immediately, and submitted the patch for review last Monday, the Chrome Web store process was slower than it typically has been for us in the past, and it wasn't until Thursday that we managed to get the hotfix out to all users, which was about ~1.5d too late (v130 had started rolling out to all users). Had to do some damage control, an email blast, etc. Pity that hotfix release-timelines are at the mercy of a random review time 🥲

But what can you do. Our takeaway lesson was that we should be developing in Chrome Canary, so we'll be well aware in advance when/if an upcoming Chrome version is going to break things 😭

Are you deploying your extension manually? Switching to upload with google CLI speeds up the process, our extensions were approved in a couple of hours.

I think developing in canary is not really necessary - this was a very special case. The fault is in the tool itself, that had no reason to set a unsupported setting as true by default. There are no other settings generated by CRXJS in the current versions that could create a similar problem in the future.

saxoncameron commented 1 month ago

Are you deploying your extension manually? Switching to upload with google CLI speeds up the process, our extensions were approved in a couple of hours.

I think developing in canary is not really necessary - this was a very special case. The fault is in the tool itself, that had no reason to set a unsupported setting as true by default. There are no other settings generated by CRXJS in the current versions that could create a similar problem in the future.

We have a pipeline that zips up the final asset bundle asset and we upload that manually, only takes a minute or so, and I like to sanity test the final zip as it uploads (testing basic installation and userflows). I really can't complain about our usual review times, it is usually within 6-12h sometimes less, or on rarer occasions within 24-48h, very rarely longer. But it does fluctuate along that spectrum. We submit every week or every other week, and this is the first issue we've had in over a year since we started doing that.

I agree with your point about the tool, but I will continue to develop in Canary from now on anyway

pietrofxq commented 1 month ago

Are you deploying your extension manually? Switching to upload with google CLI speeds up the process, our extensions were approved in a couple of hours. I think developing in canary is not really necessary - this was a very special case. The fault is in the tool itself, that had no reason to set a unsupported setting as true by default. There are no other settings generated by CRXJS in the current versions that could create a similar problem in the future.

We have a pipeline that zips up the final asset bundle asset and we upload that manually, only takes a minute or so, and I like to sanity test the final zip as it uploads (testing basic installation and userflows). I really can't complain about our usual review times, it is usually within 6-12h sometimes less, or on rarer occasions within 24-48h, very rarely longer. But it does fluctuate along that spectrum. We submit every week or every other week, and this is the first issue we've had in over a year since we started doing that.

I agree with your point about the tool, but I will continue to develop in Canary from now on anyway

Oh that's probably it then. You can still test the final zip using the CLI tool by disabling auto-publish. In our flow in github actions we zip the extension, send it to cloud storage, upload it to google using the API but also send a download link to the zip in cloud storage to a slack channel. When we are done testing we just click "submit to review" in the google store. This speeds up the review process, and also avoid potentially submitting the wrong zip

Toumash commented 1 month ago

Similiar here, amazing github action deploying it.

    - name: Upload & release
      uses: mnao305/chrome-extension-upload@3.0.0
      with:
        file-path: extension.zip
        extension-id: bgkpehhnbobnalcmakjmllahilkcfelp
        client-id: ${{ secrets.CHROME_CLIENT_ID }}
        client-secret: ${{ secrets.CHROME_CLIENT_SECRET }}
        refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }}

You can set publish: false so that you need to manually approve the deploy

https://github.com/mnao305/chrome-extension-upload

rendomnet commented 1 month ago

I went on a similar plugin hack as @salmin89 but in my use-case, extension build steps are already ignored while in dev mode. That way, this plugin is all you need:

import fs from 'fs';
import type { ManifestV3Export } from '@crxjs/vite-plugin';

// ManifestV3 type is not exported the lib, but we can infer it
type ManifestV3 = Exclude<
  ManifestV3Export,
  Promise<any> | ((...args: any[]) => any)
>;

const patchDynamicUrlsPlugin = {
  name: 'patch-dynamic-urls-plugin',
  writeBundle() {
    const manifestPath = 'dist/manifest.json'; // Edit that part if your 'outDir' is different
    const manifestContent: ManifestV3 = JSON.parse(
      fs.readFileSync(manifestPath, 'utf8'),
    );

    if (manifestContent.web_accessible_resources) {
      manifestContent.web_accessible_resources =
        manifestContent.web_accessible_resources.map(resource => ({
          ...resource,
          use_dynamic_url: false,
        }));
    }

    fs.writeFileSync(manifestPath, JSON.stringify(manifestContent, null, 2));
  },
};

Then add it to your plugins among the ones that need to run when building extension.

plugins: [
  // ... other plugins
  ...(isExtensionBuild ? [crxjs(...), patchDynamicUrlsPlugin] : [])
]

this didnt helped me. Same error.

rendomnet commented 1 month ago

FIX WITH PATCH-PACKAGE (DEV AND BUILD)

Add patch-package:

yarn add --dev patch-package

Change the use_dynamic_url flag to false in node_modules/@crxjs/vite-plugin/dist/index.mjs in lines 1842 and 1924:

use_dynamic_url: false

Run patch-package:

npx patch-package @crxjs/vite-plugin

Add patch-package to postinstall script in package.json:

"postinstall": "patch-package"

This fixes the issue at the source so it will work correctly in both dev and prod builds

PS: If you are using yarn 3, this can be fixed with yarn patch instead of patch-package`

this will work with pnpm?

Toumash commented 1 month ago

FIX WITH PATCH-PACKAGE (DEV AND BUILD)

Add patch-package:

yarn add --dev patch-package

Change the use_dynamic_url flag to false in node_modules/@crxjs/vite-plugin/dist/index.mjs in lines 1842 and 1924:

use_dynamic_url: false

Run patch-package:

npx patch-package @crxjs/vite-plugin

Add patch-package to postinstall script in package.json:

"postinstall": "patch-package"

This fixes the issue at the source so it will work correctly in both dev and prod builds PS: If you are using yarn 3, this can be fixed with yarn patch instead of patch-package`

this will work with pnpm?

https://pnpm.io/scripts

jacksteamdev commented 1 month ago

@sebastienfontaine I've merged #927 and released v2.0.0-beta.26 which fixes your repro for me. Please take a look and let me know if this issue persists.

jacksteamdev commented 1 month ago

@everyone Please pop over to the Chromium issue and click the +1 at the top of the page to let them know you're affected. It would be nice to get use_dynamic_url fixed for web-accessible resources.

image
sebastienfontaine commented 1 month ago

@sebastienfontaine I've merged #927 and released v2.0.0-beta.26 which fixes your repro for me. Please take a look and let me know if this issue persists.

Thanks for the update. I’ve tested it, and it looks like the fix in v2.0.0-beta.26 resolves the issue on my end. I’ll keep monitoring, but for now, everything seems to be working as expected. Thanks again!

Alex-Golovin commented 1 month ago

@sebastienfontaine I've merged #927 and released v2.0.0-beta.26 which fixes your repro for me. Please take a look and let me know if this issue persists.

Thanks for the update. I’ve tested it, and it looks like the fix in v2.0.0-beta.26 resolves the issue on my end. I’ll keep monitoring, but for now, everything seems to be working as expected. Thanks again!

it works for me too

allcentury commented 1 month ago

v2.0.0-beta.26 fixes the error (thank you!) but I've lost HMR in my content script - wanted to confirm that's expected? I'm using React 18

SanderMuller commented 1 month ago

Will there be a patch for v1? It's nice that v2.0.0-beta.26 fixes the error, but I would rather not ship a major upgrade in beta stage as a hotfix for this issue

kyr0 commented 1 month ago

Works for me as well. But good lord this has been a major headache for me today. Thanks for the timely fix though @jacksteamdev!