How to import npm packages in content script in an extension?

I’m trying to make a Firefox extension. So far all I have in my content script is

import isEven from 'is-even'

and I get back SyntaxError: import declarations may only appear at top level of a module. I then found this thread that suggests using dynamic import, so I tried

async function main() {
  // wrapped in a function because top-level await wasn't allowed
  const isEven = await import('is-even')
}
main(); 

and now I get The specifier “is-even” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”.. It’s not supposed to be a relative path, so I don’t understand this error.

What do I need to change?

I still don’t know how to fix this, but I ended up trying a bundler like that thread suggests (Rollup), it took a while to config but I made it work.

I can add that webextensions doesn’t natively support NodeJS and NPM, which it sounds to me like you trying to use features of.
With webextension you are left with standard javascript + some webextensions extras.
Without being an expert in either NodeJS, NPM or bundlers, I guess a bundler will work as a “pre-compiler” and get the dependencies from NPM and pack it into a standard JS “bundle” which browsers also understands.

(but someone else can properly explain it better or more precise :slight_smile: )

1 Like

To clarify what’s happening here - in order to be able to use the import, you need to load your script as “module”. More info:

The modules are amazing and introducing them to vanilla JS was a big deal!
See also:

However, modules support is not fully implemented in all parts of extensions, specifically in the content scripts:

I think it works in the background scripts, but you need to supply html yourself and mark the script as module. The shorter way of declaring it only in manifest file is not yet implemented:

Using Rollup is indeed a good solution for this issue (unlike WebPack, it adds no overhead and it’s easy to setup).