How to Import Local JS Files into Content Scripts?

452 views
Skip to first unread message

Bekir Ozturk

unread,
Jul 17, 2023, 8:50:09 AM7/17/23
to Chromium Extensions
I wanted to shorten some stuff, for example document.querySelectorAll() into dom.qsa().

The code is, basically;

const dom = {}
dom.qsa = function (query) {
    return document.querySelectorAll(query);
}
export default dom;

And in my popup.js file i can just write;

import dom from "./dom.js";
var elements = dom.qsa(".element");

That works perfectly. I obviously have other things for dom and other stuff like i18n, storage, etc.

But in contentScript, it doesn't allow me to use that. It says: Uncaught SyntaxError: Cannot use import statement outside a module.

Why it doesn't let me? It's a local file, uses extension's file. Is there a way to do that?

wOxxOm

unread,
Jul 17, 2023, 10:22:09 AM7/17/23
to Chromium Extensions, Bekir Ozturk
Static import of other extension scripts is not possible in a content script, it's just not implemented, but if you use a bundler like webpack you can use static imports in the source code and then make a single bundle for the content script.

The usual solution is to use a standard script (not a module) with global functions and include it before your main content script like "content_scripts": [{"js": ["dom.js", "content.js"], "matches": "..."}]. The same script can be loaded in other places of the extension e.g. in the popup via <script src=...></script> tag.

You can also use a dynamic import (example), which is asynchronous. Note that it requires exposing the file in web_accessible_resources  thus making your extension detectable until use_dynamic_url parameter is implemented in https://crbug.com/1383176.

Bekir Ozturk

unread,
Jul 17, 2023, 11:42:14 AM7/17/23
to Chromium Extensions, wOxxOm, Bekir Ozturk
Thanks for the answer.

I added dom.js in manifest.json as you said. Removed the export part in dom.js. For popup, I removed the type="module" when including in html file.

But I also use storage.js (for chrome.storage.local/sync stuff). When I remove "export default storage;" from there, my background.js (service worker) gives an error: Uncaught SyntaxError: The requested module './storage.js' does not provide an export named 'default'.

If I change "import storage from "./storage.js";" into "import "./storage.js";" the error changes into this where storage was first used: Uncaught (in promise) ReferenceError: storage is not defined.

I removed the "type: "module"" part for service worker in manifest.json. Changed the import into "importScripts("storage.js");", seems working now. Is this a viable solution?

wOxxOm

unread,
Jul 17, 2023, 11:46:40 AM7/17/23
to Chromium Extensions, Bekir Ozturk, wOxxOm
You did everything right, importScripts is the correct method for non-module workers.

Bekir Ozturk

unread,
Jul 17, 2023, 11:48:41 AM7/17/23
to Chromium Extensions, wOxxOm, Bekir Ozturk
Thank you for your answers and the solution. Have a nice day.
Reply all
Reply to author
Forward
0 new messages