In Chrome 61, support for modules in JavaScript was added. Right now I am running Chrome 63.
I am trying to use import
/export
syntax in Chrome extension content script to use modules.
In manifest.json
:
"content_scripts": [ { "js": [ "content.js" ], } ]
In my-script.js
(same directory as content.js
):
'use strict'; const injectFunction = () => window.alert('hello world'); export default injectFunction;
In content.js
:
'use strict'; import injectFunction from './my-script.js'; injectFunction();
I receive this error: Uncaught SyntaxError: Unexpected identifier
If I change the import syntax to import {injectFunction} from './my-script.js';
I get this error: Uncaught SyntaxError: Unexpected token {
Is there some issue with using this syntax in content.js
in Chrome extension (since in HTML you have to use <script type="module" src="script.js">
syntax), or am I doing something wrong? It seems strange that Google would ignore support for extensions.
Importing can be done in various ways:Node js doesn't support ES6 import directly. If we try to use import for importing modules directly in node js it will throw out the error.
Safari, Chrome, Firefox and Edge all support the ES6 Modules import syntax. Here's what they look like. Simply add type="module" to your script tags and the browser will load them as ES Modules. The browser will follow all import paths, downloading and executing each module only once.
Content scripts are files that run in the context of web pages. By using the standard Document Object Model (DOM), they are able to read details of the web pages the browser visits, make changes to them, and pass information to their parent extension.
As it's already mentioned, for background script, it's good idea to use background.page
and use <script type="module">
to kick your JavaScript.
The problem is content script
, and injecting <script>
tag with type
attribute can be a solution.
Another approach than injecting script tag is to use dynamic import
function. By this approach, you don't need to loose scope of chrome
module and still can use chrome.runtime
or other modules.
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'll also need to declare the imported scripts in manifest's Web Accessible Resources:
{ "web_accessible_resources": [ "your/content_main.js" ] }
For more details:
chrome.runtime.getURL
Hope it helps.
I managed to find a workaround.
First of all, it’s important to say that content scripts don’t support modules as of January 2018. This workaround sidesteps the limitation by embedding module script
tag into the page that leads back to your extension.
This is my manifest.json
:
"content_scripts": [ { "js": [ "content.js" ] }], "web_accessible_resources": [ "main.js", "my-script.js" ]
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
into the webpage as a module script.
All my business logic is now in main.js
.
For this method to work, main.js
(as well as all scripts that I will import
) must be in web_accessible_resources
in the manifest.
my-script.js
'use strict'; const injectFunction = () => window.alert('hello world'); export {injectFunction};
And in main.js
this is an example of importing the script:
'use strict'; import {injectFunction} from './my-script.js'; injectFunction();
This works! No errors are thrown, and I am happy. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With