parcel-bundler / parcel

The zero configuration build tool for the web. 📦🚀
https://parceljs.org
MIT License
43.5k stars 2.27k forks source link

[Web Extension Packager] web_accessible_resources includes **bundle-text** assets, empty content_scripts.css field #8850

Open Doliman100 opened 1 year ago

Doliman100 commented 1 year ago

🐛 bug report

When css is imported as text, the content_scripts.css or web_accessible_resources manifest fields shouldn't contain it. Because it doesn't exist as a file and already included in content.js. Currently, the web_accessible_resources field contains a reference to non-existing file. The content_scripts.css field is empty, but still included in resulting manifest.json. It should not be included if it is empty.

🎛 Configuration (.babelrc, package.json, cli command)

cli command

npx parcel build src/manifest.json --config @parcel/config-webextension --no-source-maps --no-content-hash

🤔 Expected Behavior

./dist/manifest.json:

{
  "content_scripts": [{
    "js": ["content.ec7ad09b.js"],
    "matches": ["<all_urls>"]
  }],
  "manifest_version": 3,
  "name": "Test Extension",
  "version": "1.0"
}

😯 Current Behavior

./dist/manifest.json:

{
  "content_scripts": [{
    "js": ["content.ec7ad09b.js"],
    "matches": ["<all_urls>"],
    "css": []
  }],
  "manifest_version": 3,
  "name": "Test Extension",
  "version": "1.0",
  "web_accessible_resources": [{
    "matches": ["<all_urls>"],
    "resources": ["content.9bf41e48.css"]
  }]
}

💻 Code Sample

./src/content.js:

import style from 'bundle-text:./style.css';

const sheet = new CSSStyleSheet();
sheet.replaceSync(style);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

./src/manifest.json:

{
  "content_scripts": [{
    "js": ["content.js"],
    "matches": ["<all_urls>"]
  }],
  "manifest_version": 3,
  "name": "Test Extension",
  "version": "1.0"
}

Distributable folder ./dist/ content: manifest.json, content.ec7ad09b.js (there is no content.9bf41e48.css).

🌍 Your Environment

Software Version(s)
Parcel 2.8.3
Node v18.14.0
npm/Yarn 9.3.1
Operating System Windows 11
github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.

fregante commented 10 months ago

Why are you importing the style this way? Extensions and Parcel both support loading styles directly:

{
  "content_scripts": [{
    "js": ["content.js"],
+   "css": ["content.css"],
    "matches": ["<all_urls>"]
  }],
  "manifest_version": 3,
  "name": "Test Extension",
  "version": "1.0"
}
Doliman100 commented 10 months ago

I'm working on an extension whose main part should only load on pages with "image/*" document.contentType. There is a small loader script that loads into every page the user visits and checks for the document.contentType. It loads the remaining content only for pages that meet the condition. That's why I can't just include this style in manifest.json. I don't need it to load on every page the user visits.

fregante commented 10 months ago

The only images with document are presumably SVG, right? Would a *.SVG glob be enough?

There's a chance that you can also do the same via chrome.scripting.injectCSS() from the background page, which is the official way to inject style.

Doliman100 commented 10 months ago

Images may not have an extension, so URL analyzing is not a solution. My extension works for .jpg, .png, .webm or any other image type supported by Chrome's default image viewer. chrome.scripting.injectCSS() injects styles and scripts asynchronously, which causes background flickering. document.adoptedStyleSheets injects styles synchronously, which means the page will not open until all styles have been applied. Here is the extension I am talking about: https://chromewebstore.google.com/detail/simple-image-viewer/ohkbjcfpicefkagfejabhddfbmkeiojm https://github.com/Doliman100/Simple-Image-Viewer

fregante commented 10 months ago

That's cool. The only thing I'd do differently is probably just load the CSS on every website and limit it to a specific class that your content.js adds. It's a super small stylesheet. But I understand if you want to be super efficient