Search code examples
javascriptfirefox-addon

Why am I getting "import declarations may only appear at the top level of a module" in my firefox extension


I am developing a firefox extension and I would like to import a function from foo.js. My directory structure looks like this

app
  js
    foo.js
  content.js
  manifest.json
  background.js

foo.js

function myFunc() {
  let hello = 'hello from foo.js';

  return hello;
}

export {myFunc};

content.js

import { myFunc } from './js/foo.js';

browser.runtime.onMessage.addListener((message) => {
  let result = myFunc();
  console.log(result);
});

manifest.json

{
  "manifest_version": 2,
  "name": "test",
  "version": "1.0.0",
  "description": "A notetaking tool for YouTube videos",
  "icons": {
    "48": "icons/border-48.png"
  },
  "background": {
    "scripts": ["background.js"]
  },
  "permissions": [
    "tabs"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_start"
    }
  ],
  "web_accessible_resources":[
    "icons/my_icon.svg",
    "js/*"
  ]
}

background.js

browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
   browser.tabs.sendMessage(tabId, {message: 'hello from background.js'});
});

This doesn't work. I get the following error in the console

import declarations may only appear at the top level of a module

I don't understand why I am getting this error in content.js, import is placed at the top of the file. I've tried some of the proposed solutions in this similar question but this doesn't work either.


Solution

  • I am going to recommend anyone dealing with this issue to read over Dhruvil Shah's answer. They reccomend using a bundler like Webpack or rollup. I was able to use Webpack to bundle everything up into a single file called main.js. Then, I changed my manifest.json file from

      ....
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["content.js"],
          "run_at": "document_start"
        }
      ],
      ....
    

    to

      ....
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["dist/main.js"],
          "run_at": "document_start"
        }
      ],
      ....
    

    Also, this video from fireship on YouTube helped me used Webpack too.