Reputation: 131
There are a bunch of similar threads on here however I cannot seem to find anything that works for me. I am building a chrome extension where I'd like to connect to a websocket. I have found a project, https://github.com/matthewlawson/lnm-socket.io, which I try to use as inspiration although I cannot make it work for me.
The server is not in the chrome extension, however I try to access it from my background.js file. That's when I get the Cannot use import statement outside a module error message. Adding "type": "module" to my package.json file doesn't seem to fix it and since it is the background file I do not have it in a script tag to place the "type": "module" in. What can I do?
Upvotes: 13
Views: 12143
Reputation: 11
I painfully had to go through some trial and error to find a solution for "Cannot use import statement outside a module" globally in my entire chrome extension setup with a contentscript, service-worker and background in manifest v3, but I have to admit that I'm also not trying to setup sth fancy like websockets, just importing some external libs getting this error too.
Solution in short: as far as I assume, you cannot have any import statements in any script that is invoked by your content script in your production build. (Maybe I'm also just to dump to make imports work in content scripts?) Building your content script separately from popup & service worker in my package manager fixed all of these issues. Service worker and popup can import from the same module.
Solution Extended Setup: Building your content scripts separately means means you resolve any import statements and therefore your content scripts will contain anything that you import and encapsulated within itself. I personally use vite as my build tool and set up a base config file with settings for every component of my extension, while also having 2 more config files that split the build for content script (1) and service worker/popup (2).
While content scripts (1) run within the context of a certain webpage, I believe the service worker and popup (2) operate in the same "environment" that belongs to the extension itself, which is the reason why if popup and service worker share certain imports/ modules, it didn't lead to any errors for me. Only if one of their imports intersected with an import in content scripts.
This is my setup in vite:
npm run buildOne && npm run buildTwo
which is how I separated those builds (for buildOne and Two you can choose anything you define)tsc -b && vite build --config TheConfigFileNameForOne.config.ts
the code roughly: base.config.ts
import { UserConfig } from 'vite';
import path, { resolve, parse } from 'path';
export function createBaseConfig(...files: string[]): UserConfig {
const root = resolve(__dirname, 'src')
const input: Record<string,string> = {}
files.forEach( (file) => {
input[parse(file).name] = resolve(root,file) //input-object format example: "background : resolve(root, 'background.ts')",
})
return {
plugins: ..., //your base configs
server: ...,
build: {
...
}
}
}
buildOne.config.ts (and analogue buildTwo):
import { defineConfig } from 'vite';
import { createBaseConfig } from './base.config.ts'
export default defineConfig( ('pathToContentScript.ts') => {
// for Two: ('pathToServiceWorker.ts','pathToPopup.html')
const baseConfig = createBaseConfig()
return {
...baseConfig,
build: {
...baseConfig.build,
// ie: some content script specific build settings here
}
}
})
Now I can run everything with npm run buildCustom
from CLI without any problems.
Note about args: you can also pass arguments (commands, modes) between those for further customization.
This solved all the issues for me. Dynamic imports don't work anyway at all in v3.
The downsides are potentially:
Maybe there is a better solution, idk!
Upvotes: 1
Reputation: 1071
The solution I found was not to change the manifest.json; instead, it was how the javascript file was loaded.
I went from
<script src="/dist/popup.js"></script>
to
<script type="module" src="/dist/popup.js"></script>
Upvotes: 2