Code Monkey home page Code Monkey logo

webpack-target-webextension's People

Contributors

crimx avatar dependabot[bot] avatar fregante avatar jack-works avatar tylerccarson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

webpack-target-webextension's Issues

Use native `import()` calls

I just tried import(chrome.runtime.getURL()) and it seems to work both in Chrome and Firefox, in content scripts and background pages 🎉

This is because the bug that your readme points to, has been marked as solved and shipped in the latest Firefox release: https://bugzilla.mozilla.org/show_bug.cgi?id=1536094

Could this plugin be modified to use import() instead of the current messaging mechanism?

Does Webpack even leave native import() calls in the bundle? In my test, import() is still converted to Webpack’s own loading mechanism and I don't see anything about raw import() calls in the docs:

https://webpack.js.org/guides/code-splitting/#dynamic-imports
https://webpack.js.org/api/module-methods/#import-1

How to exclude files from this plugin (unsafe context)

I have a file that is being injected in the “unsafe context” via script tag in order to access the data/variables in the live website. This file is being executed outside the extension context and is not a content script.

How do you suggest I exclude it from this plugin? If it included import calls they’re now broken. Do you think it’s possible to disable the plugin on specific files, either via webpack config or plugin config?

The only option I’m aware of is to have a whole new webpack config/build specific to this file in order to exclude this plugin.

Limits of the HMR client

I noticed that this plugin supports HMR, but it's not clear to me what's required to make it work and in what context it can work.

I load my extensions via web-ext run and they're reloaded (kind of) automatically when my dist folder changes. This causes the content scripts to lose connection with the background page so they will no longer work until the page is refreshed.

Does HMR only work on chrome-extension:// pages?

Does HMR only work on self-contained React components? i.e. that don't require messaging.

Do I need to set up some "unload" mechanism for the previous content script? Currently a web-ext reload will just reinject content script and every change to the page will be reapplied (unless I have code to block it)

It doesn't work if the page contains an element with `id="browser"`

Elements with ids will automatically become globals so this check is truthy even when it shouldn't be:

const isModern = typeof browser !== 'undefined'

Gotta love Netscape.

Screen Shot 6

Test URL: https://ghosttext.fregante.com/

Suggested fix: use this or its globalThis-less equivalent:

const isModern = typeof globalThis.browser?.runtime?.getURL === 'function'

Content scripts are subject to target page's CSP?

README says "In content scripts native dynamic import subjects to target page content security policy".
Do you have any sources to back that up?

From a bit of testing it looks to me that it's not true.
For example, here, on GitHub, if you open the console and try typing

import("https://www.example.com/1.js")

it will refuse to do it with reference to the website's CSP, but my extension, which uses import(), imports its script just fine (it even appears in the Network tab of dev tools).
Also, here are docs for Microsoft Edge extension developers: https://docs.microsoft.com/en-us/microsoft-edge/extensions-chromium/store-policies/csp#content-scripts, which specifically state the opposite.
Mozilla docs are more general, there is no section for content scripts specifically: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy

`serviceWorkerEntry` breaks `mini-css-extract-plugin` in MV3 only

I'm opening this issue to collect some information I find.

Error

Appears in the background worker on load:

Screenshot

Repro

I think the repro so far is:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    // This is the order in my config
    new WebExtensionTarget({
      weakRuntimeCheck: true,

      background: {
        // it works with `pageEntry` on MV2
        serviceWorkerEntry: "background",
      }
    }),
    new MiniCssExtractPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};
import './input.css'
console.log('js loaded')
* {
  color: hotpink;
}

Related

First seen in

Error loading dynamic modules in frames in Webpack 5

Thanks for your work on this extension! We're seeing problems with dynamic imports failing for iframes with Webpack 5. I think the problematic line might be:

https://github.com/crimx/webpack-target-webextension/blame/49b43992aafd53faf6493cbd33ba54e289ba3078/lib/background.js#L13

This should probably be sender.frameId? The sender.tab.frameId expression is undefined.

I am curious as to how this was working previously as that line has been there over a year. Maybe Chrome recently changed what's passed with sender.tab? In the MDN documentation the tab https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/MessageSender won't have a frameId

Webpack 5.26+: outputPath.replace is not a function

I found an issue with this line:

https://github.com/crimx/webpack-target-webextension/blob/d0dc5c448592875b69a42e329736072b11744596/lib/webpack5/AutoPublicPathRuntimeModule.js#L27

Which causes an unhelpful error:

ERROR in webpack/runtime/publicPath
outputPath.replace is not a function

because Webpack's getUndoPath function accepts a string, not a boolean, since v5.26:

https://github.com/webpack/webpack/blob/5dd661cc39c1c59c70859afa55757cdb483418cc/lib/util/identifier.js#L309-L313

webpack/webpack@7dc945f

It appears to fail on sandboxed frames without `allow-scripts`

I'm still looking into it, but it seems that the first chunk runs correctly, but then anything import()'d fails with this error:

contentScript.js:18475 Uncaught (in promise) ChunkLoadError: Loading chunk vendors-node_modules_emotion_react_dist_emotion-react_browser_esm_js failed.
(undefined: undefined)
    at __webpack_require__.f.j (contentScript.js:18475:29)
    at contentScript.js:18249:40
    at Array.reduce (<anonymous>)
    at __webpack_require__.e (contentScript.js:18248:67)
    at initContentScript (contentScript.js:18610:229)
    at contentScript.js:18630:10
    at contentScript.js:18638:3
    at contentScript.js:18640:12

It looks like import works fine though, I can run this in the console for that frame:

const code = 'export const foo = 123'
const imported = await import(`data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`)
console.log(imported.foo) // Should print 123

Examples aren't complete

I'm trying to ad HMR to my extension but webpack serve appears to run this code (on css files 🤔) and fail:


ERROR in ./src/vendors/theme/app/app.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
HookWebpackError: No chrome or browser runtime found
    at tryRunOrWebpackError (./node_modules/webpack/lib/HookWebpackError.js:88:9)
    at __webpack_require_module__ (./node_modules/webpack/lib/Compilation.js:4979:12)
    at ./node_modules/webpack/lib/Compilation.js:5003:11
    at symbolIterator (./node_modules/neo-async/async.js:3485:9)
    at processTicksAndRejections (node:internal/process/task_queues:78:11)
-- inner error --
Error: No chrome or browser runtime found
    at Object.get runtime [as runtime] (webpack/runtime/publicPath:3:81)
    at webpack/runtime/publicPath:13:37
    at ./node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js:460:11
    at Hook.eval [as call] (eval at create (./node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:9:1)
    at ./node_modules/webpack/lib/Compilation.js:4981:39
    at tryRunOrWebpackError (./node_modules/webpack/lib/HookWebpackError.js:83:7)
    at __webpack_require_module__ (./node_modules/webpack/lib/Compilation.js:4979:12)
    at ./node_modules/webpack/lib/Compilation.js:5003:11
    at symbolIterator (./node_modules/neo-async/async.js:3485:9)
    at processTicksAndRejections (node:internal/process/task_queues:78:11)

Generated code for webpack/runtime/publicPath
 1 | var isBrowser = !!(() => { try { if (typeof browser.runtime.getURL === "function") return true } catch(e) {} })()
 2 | var isChrome = !!(() => { try { if (typeof chrome.runtime.getURL === "function") return true } catch(e) {} })()
 3 | var runtime = isBrowser ? browser : isChrome ? chrome : { get runtime() { throw new Error("No chrome or browser runtime found") } }
 4 | var scriptUrl;
 5 | if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
 6 | var document = __webpack_require__.g.document;
 7 | if (!scriptUrl && document) {
 8 |    if (document.currentScript)
 9 |            scriptUrl = document.currentScript.src
10 | }
11 | // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
12 | // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
13 | if (!scriptUrl) scriptUrl = runtime.runtime.getURL("/");
14 | scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
15 | __webpack_require__.p = scriptUrl;

So I wanted to test it out using the examples linked in the readme but everything is missing, all the dependencies and the linked files. Could you include them all to ensure they can be run as-is?

Conflict with HtmlWebpackPlugin - "Error: No chrome or browser runtime found"

Hello,
I'm trying to fix the dynamic imports in MV3 so I've added new WebExtension into the plugins array:

      new WebExtension({
        background: {
          entry: `background_gsd.worker`,
          // !! Add this to support manifest v3
          manifest: 3,
        },
      }),

And it seems to fix the background service worker, but at the same time my compilation now fails in the HtmlWebpackPlugin, which doesn't make sense to me:

ERROR in   Error: No chrome or browser runtime found

  - reload.html:81 Object.get runtime [as runtime]
    C:/Users/juraj/git/addons/GroupSpeedDial/src/reload/reload.html:81:92

  - reload.html:83
    C:/Users/juraj/git/addons/GroupSpeedDial/src/reload/reload.html:83:89

  - reload.html:84
    C:/Users/juraj/git/addons/GroupSpeedDial/src/reload/reload.html:84:13

  - reload.html:118
    C:/Users/juraj/git/addons/GroupSpeedDial/src/reload/reload.html:118:12

  - node:vm:139 Script.runInContext
    node:vm:139:12

  - index.js:142 HtmlWebpackPlugin.evaluateCompilationResult
    [GroupSpeedDial]/[html-webpack-plugin]/index.js:142:28

  - index.js:324
    [GroupSpeedDial]/[html-webpack-plugin]/index.js:324:26

  - async Promise.all

  - async Promise.all

Removing the new WebExtension(... from the plugins list fixes the problem so there must be some correlation I don't see.
Can you help? Or do I need to provide some example project?
Thanks!

Rewrite HMR client?

Hi, I'd like to know is it possible for a webpack plugin to re-write the HMR client?

When running HMR in the content script, for an unknown reason it will be blocked by CSP policy.

Refused to connect to 'https://localhost:8080/sockjs-node/info?t=1603432704212' because it violates the following Content Security Policy directive: ......

If it is possible, I'd like to contribute an HMR client that works for the Web Extension.

missing webpack/runtime/load script in background.js

We have a background script that is started like so.

// ./background.js
import { startApi } from "@sendnodes/pokt-wallet-background"

startApi()

However, this extension fails to add this runtime part in the webpack output. It never fetches all of the modules correctly and so our background script exits without executing the startApi logic.

/******/ 	/* webpack/runtime/load script */
/******/ 	(() => {
/******/ 		var isBrowser = !!(() => { try { return browser.runtime.getURL("/") } catch(e) {} })()
/******/ 		var isChrome = !!(() => { try { return chrome.runtime.getURL("/") } catch(e) {} })()
/******/ 		var runtime = isBrowser ? browser : isChrome ? chrome : (typeof self === 'object' && self.addEventListener) ? { get runtime() { throw new Error("No chrome or browser runtime found") } } : { runtime: { getURL: x => x } }
/******/ 		var __send__ = (msg) => {
/******/ 			if (isBrowser) return runtime.runtime.sendMessage(msg)
/******/ 			return new Promise(r => runtime.runtime.sendMessage(msg, r))
/******/ 		}
/******/ 		var classicLoader = (url, done, chunkId) => {
/******/ 			__send__({ type: 'WTW_INJECT', file: url }).then(done, (e) => done(Object.assign(e, { type: 'missing' })))
/******/ 		}
/******/ 		var scriptLoader = (url, done, chunkId) => {
/******/ 			var script = document.createElement('script')
/******/ 			script.src = url
/******/ 			script.onload = done
/******/ 			script.onerror = done
/******/ 			document.body.appendChild(script)
/******/ 		}
/******/ 		var workerLoader = (url, done, chunkId) => {
/******/ 			try { importScripts(url); done() } catch (e) { done(e) }
/******/ 		}
/******/ 		var isWorker = typeof importScripts === 'function'
/******/ 		if (location.protocol.includes('-extension:')) __webpack_require__.l = isWorker ? workerLoader : scriptLoader
/******/ 		else if (!isWorker) __webpack_require__.l = classicLoader
/******/ 		else { throw new TypeError('Unable to determinate the chunk loader: content script + Worker') }
/******/ 	})();

The only way to get this plugin to get this part added is to convert our background script is to use dynamic imports. Then, that runtime portion gets added.

setTimeout(async () => {
  const { startApi } = await import("@sendnodes/pokt-wallet-background")

  startApi()
}, 1);

I don't know enough about webpack compilation steps to be much more help than that, but maybe this has to do with our webpack setup. This is what our plugin looks like.

new WebExtension({
  background: {
    entry: 'background',
    // !! Add this to support manifest v3
    manifest: browser == 'chrome' ? 3 : 2,
    classicLoader: true
  },
  weakRuntimeCheck: true,
  hmrConfig: false
}),

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.