Search code examples
google-chrome-extensionimportsocket.ioservice-worker

How to import a js file in a Chrome extension service worker?


I am trying to use socket.io library in a service worker of y Chrome extension, but when I try to load it in Chrome I get the error: Uncaught SyntaxError: "Cannot use import statement outside a module".

I got the library from here, then I saved the it in my extension folder, in socketIo.js:

enter image description here

Then in my service_worker.js, I try to import it:

import io from './socketIo.js';
const socket = io("http://localhost:3002");

Since it as service worker, I do not attach it to my extension html file, therefore I can't simply set the worker as a module like this:

<script type="module" src="./service_worker.js"></script>. 

Also, since extensions are not Node.js applications, they don't have a package.json where I could set the property "type": "module.

And as you can see I used both the relative path and the extension of the file imported, as suggested here: Chrome Extension Service Worker not Supporting Importing Other JS Files or NPM Packages

Now I've added the ES module version of socket.io and its "map" file. And updated my service worker in manifest.json to be a ES module too:

enter image description here

enter image description here

enter image description here

But when I tried to load the extension again, I get this warning: "Service worker registration failed. Status code: 3", and the generic error:

enter image description here


Solution

  • Since it as service worker, I do not attach it to my extension html file, therefore I can't simply set the worker as a module like this: .

    Also, since extensions are not Node.js applications, they don't have a package.json where I could set the property "type": "module.

    Register the service worker

    You can optionally specify an extra field of "type": "module" to include the service worker as an ES Module, which allows you to import further code.

    manifest.json

    {
        "manifest_version": 3,
        "name": "socket.io",
        "version": "1.0",
        "background": {
            "service_worker": "background.js",
            "type": "module"
        }
    }
    

    But the socket.io version you're using isn't an ES Module:

    Uncaught SyntaxError: The requested module '/socket.io.js' does not provide an export named 'default'
    

    So I downloaded socket.io.esm.min.js and socket.io.esm.min.js.map from https://cdn.socket.io/4.5.3

    I don't know if they have an ES Module version of socket.io 1.7.3

    Including the .map file in the extension prevents this error in the service worker console:

    DevTools failed to load source map: Could not load content for chrome-extension://cfdinlnmiepoligakoinbffeaphkfmmp/socket.io.esm.min.js.map: System error: net::ERR_FILE_NOT_FOUND

    background.js

    import io from "/socket.io.esm.min.js";
    const socket = io("http://localhost:3002");
    

    The service worker console still gets flooded with this error:

    Event handler of 'beforeunload' event must be added on the initial evaluation of worker script.

    But I think there's a solution for that on Stackoverflow.

    Or not:

    Also, put the libraries socket.io.esm.min.js and socket.io.esm.min.js.map inside the same folder of service worker, in the same level (not in a sub folder).

    After you made this changes, just refresh you extension in chrome://extensions/. But if this doesn't work, delete your extension and load it unpacked again.