Chrome Extension: Import ES6 modules in content scripts
P粉141035089
P粉141035089 2023-08-27 22:19:00
0
2
589
<p>In <strong>Chrome 61</strong>, support for JavaScript modules was added. Now I'm running Chrome 63. </p> <p>I'm trying to use a module in a Chrome extension content script using the <code>import</code>/<code>export</code> syntax. </p> <p>In<strong><code>manifest.json</code></strong>:</p> <pre class="brush:php;toolbar:false;">"content_scripts": [ { "js": [ "content.js" ], } ]</pre> <p>In<strong><code>my-script.js</code></strong> (with <strong><code>content.js</code></strong> same directory):</p> <pre class="brush:php;toolbar:false;">'use strict'; const injectFunction = () => window.alert('hello world'); export default injectFunction;</pre> <p>In<strong><code>content.js</code></strong>:</p> <pre class="brush:php;toolbar:false;">'use strict'; import injectFunction from './my-script.js'; injectFunction();</pre> <p>I get this error:<strong><code>Uncaught syntax error: Unexpected identifier</code></strong></p> <p>If I change the import syntax to <code>import {injectFunction} from './my-script.js';</code> I get this error: <strong><code>Uncaught SyntaxError: Unexpected token {</code></strong>< /p> </p><p>Is there a problem using this syntax in <strong><code>content.js</code></strong> in the Chrome extension (because in HTML you have to use < ;code> <script type="module" src="script.js "></code> syntax), or am I doing something wrong? It seems strange that Google is ignoring support for extensions. </p></script> </code></p>
P粉141035089
P粉141035089

reply all(2)
P粉739079318

Use dynamic import() function.

Unlike the unsafe workaround using elements, this workaround runs in the same secure JS environment (isolated world of content scripts) and your imported modules can still access global variables As well as functions for the initial content script, including the built-in chrome API, such as chrome.runtime.sendMessage.

In content_script.js it looks like

(async () => {
  const src = chrome.runtime.getURL("your/content_main.js");
  const contentMain = await import(src);
  contentMain.main();
})();

You also need to declare the imported script in the manifest's Web Accessible Resources:

// ManifestV3

  "web_accessible_resources": [{
     "matches": ["<all_urls>"],
     "resources": ["your/content_main.js"]
   }],

// ManifestV2

  "web_accessible_resources": [
     "your/content_main.js"
  ]

Learn more details:

Hope it helps.

P粉797004644

Disclaimer

First, it’s important to note that as of January 2018, content scripts do not support modules. This workaround works around the restriction to your extension by embedding the module script tag into the returned page.

This is an unsafe solution!

Web scripts (or other extensions) can exploit your code and extract/spoof data by using setters/getters, proxies on Object.prototype and other prototypes functions and /or the global object, because the code inside the script element runs in the JS context of the page, rather than in the secure isolated JS environment that runs content scripts by default.

A safe workaround is the dynamic import() shown in another answer here.

Solution

This is my manifest.json:

    "content_scripts": [ {
       "js": [
         "content.js"
       ]
    }],
    "web_accessible_resources": [
       "main.js",
       "my-script.js"
    ]

Please note that I have two scripts in web_accessible_resources.

This is my content.js:

    'use strict';
    
    const script = document.createElement('script');
    script.setAttribute("type", "module");
    script.setAttribute("src", chrome.extension.getURL('main.js'));
    const head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
    head.insertBefore(script, head.lastChild);

This will insert main.js as a module script into the web page.

All my business logic is now in main.js.

For this method to work, main.js (and all the scripts I import into) must be located in web_accessible_resources in the manifest .

Usage example: my-script.js

    'use strict';
    
    const injectFunction = () => window.alert('hello world');
    
    export {injectFunction};

In main.js, this is an example of the import script:

    'use strict';
    
    import {injectFunction} from './my-script.js';
    injectFunction();

This works! No errors were thrown and I was happy. :)

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template