Tampermonkey / tampermonkey

Tampermonkey is the most popular userscript manager, with over 10 million users. It's available for Chrome, Microsoft Edge, Safari, Opera Next, and Firefox.
GNU General Public License v3.0
4.24k stars 419 forks source link

ISSUE - Requiring a file containing an export #1717

Closed Malix-Labs closed 1 year ago

Malix-Labs commented 1 year ago

Problem

Requiring a file containing an export causes an "Unexpected token 'export'" error image

The userscript is not even running after it.

Exemple

Requiring the firebase-app.js v9 files such as the firebase-app.js v9.17.1 file

// ==UserScript==
// @name         Firebase Implementation Example
// @version      1.0.0
// @description  Firebase Implementation Example
// @author       -
// @match        https://github.com/*
// @require      https://www.gstatic.com/firebasejs/9.17.1/firebase-app.js
// ==/UserScript==

(function() {

    'use strict';

    console.log("Tampermonkey: \"Firebase Implementation Exemple\" script start");

})();
Malix-Labs commented 1 year ago

@derjanb do you know if there is a workaround? This issue is completely blocking our production

7nik commented 1 year ago

There is just no way to use ES modules in userscripts.

The best you can do is to use dynamic import:

(async function() {

    'use strict';

        const firebase = await import("https://www.gstatic.com/firebasejs/9.17.1/firebase-app.js");

    console.log("Tampermonkey: \"Firebase Implementation Exemple\" script start", firebase);

})();

Another way is to build Firebase locally as UMD and host somewhere. Or build the entire userscript locally and ship compiled and tree-shaked code. There even are plugins for bundlers.

derjanb commented 1 year ago

The best you can do is to use dynamic import:

Good idea! That was fast. :-) Thanks.

@Malix-Off

export needs type module which is incompatible with Tampermonkey's sandbox.

Please use webpack as explained here to bundle your script.

or manually add a script tag. This however makes your code completely public to the page and works on pages with no CSP only!

// ==UserScript==
// @name         Firebase Implementation Example
// @version      1.0.0
// @description  Firebase Implementation Example
// @author       -
// @match        https://example.com/*
// @grant        GM_addElement
// ==/UserScript==

const s = GM_addElement('script', { textContent: `
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-app.js";

window.initializeApp = initializeApp;
runOnLoad();
`, type: 'module' });

unsafeWindow.runOnLoad = () => console.log(unsafeWindow.initializeApp);
Malix-Labs commented 1 year ago

Hello again @derjanb and @7nik and thanks you both for your answer, the dynamic import workaround did the trick.

@derjanb, from your comment i tried to bundle it with this guide, but i didn't found a workaround to make it work for an userscript unfortunately

7nik commented 1 year ago

How exactly have you made the bundle?

I had a really good experience using vite-plugin-monkey to develop and build a userscript (TS + Svelte in my case)

Malix-Labs commented 1 year ago

How exactly have you made the bundle?

I had a really good experience using vite-plugin-monkey to develop and build a userscript (TS + Svelte in my case)

Hello again!

I'm currently doing the same thing now ahah, thanks for your advices <3