javascriptgoogle-chrome-extensionfirefox-addon

using executeScript with webextension-polyfill & vite in manifest v2


Context

I'm developing a chrome extension using samrum/create-vite-plugin-web-extension which user vite to bundle all the code. In this project, I would like to use executeScript and pass arguments to the script from popup.js.

I'm able to implement this in manifest v2 if i'm using Vanilla JS WITHOUT any frameworks and bundlers with below code

// Vanilla JS - manifest v2 (popup.js) - OPTION 2
chrome.tabs.executeScript(tabId, {
    code: `var eleID = '${eleID}'; var type = '${type}'; var headerHeight = ${offsetHeight};`
}, function () {
    chrome.tabs.executeScript(tabId, { file: './executeScript.js' });
});
// manifest v2 (executeScript.js)

scrollToTarget(eleID, type, headerHeight);

function scrollToTarget(eleID, type, headerHeight = 40) {
   console.log({eleID, type, headerHeight);
}

Problem

But, since I'm using the Vite bundler (samrum/create-vite-plugin-web-extension), I'm not able to achieve the same result in manifest v2, because the name of the bundled file is dynamically generated and the name of the function to execute is also minimized during bundling. Below is what I tried:

OPTION 1:

this give the following error:

Could not load file: './executeScript.js'.
Note that the filename after bundling is different executeScript.1e145e3d.js

browser.tabs.executeScript(tabId, { file: "../executeScript.js" }).then(() => {
    browser.tabs.executeScript(tabId, {
        allFrames: false,
        code: "ht('" + eleID + "', '" + type + "', " + (offsetHeight + 10) + "); ",
    });
});

OPTION 2:

this give the following error:

scrollToTarget is not defined
Note that the function name after bundling is different - eg function ht

browser.tabs.executeScript(tabId, {
    allFrames: false,
    code: "scrollToTarget('" + eleID + "', '" + type + "', " + (offsetHeight + 10) + "); ",
});

Additional info:

I was able to successfully implement this in manifest v3 using the new chrome.scripting API. Below is the code I'm using to do that (reference):

popup.js (Manifest v3)

// Code working in manifest v3 (popup.js)
chrome.scripting.executeScript({target: {tabId}, files: ['./executeScript.js']}, () => {
  chrome.scripting.executeScript({
    target: {tabId},
    args: [eleID, type, offsetHeight + 10],
    func: (...args) => scrollToTarget(...args),
  });
});
// executeScript.js
function scrollToTarget(eleID, type, headerHeight = 40) {
  console.log({eleID, type, headerHeight);
}

Solution

  • Even after implementing the code from my other answer, I was getting an error in Firefox with Manifest v2 (even though manifest v2 is working fine in Chrome).

    So after some search, I decided the expose the scrollToTraget function from executeScript.js to the global window object (as suggested in this answer). This way I also won't have to use the file in executeScript, I can directly use the window.scrollToTraget.

    Below is the code:

    // executeScript.js
    export default function scrollToTraget_Main(eleId, type, headerHeight = 40) {
    // ...
    }
    
    // contentScript_main.js
    // enable import in content script using dynamic import: https://stackoverflow.com/a/53033388/6908282
    
    import scrollToTarget from "../executeScript/executeScript"
    window.scrollToTarget = scrollToTarget;
    
    // popup.js
    browser.tabs.executeScript(tabId, {
        allFrames: false,
        code: "window.scrollToTarget('" + eleID + "', '" + type + "', " + offsetHeight + "); ",
    });
    

    Note:

    Note that you cannot use import in contentScript by default, you will have to enable it by using dynamic import