1

I am developing a Chrome Extension with React. In my service worker file, background.js, I need to import another JS file, which for simplicity, only exports an empty {} for now.

background.js

import store from './testImport';    
console.log("Hello Service Worker.")

testImport.js

export default {}

but with no success. I get this error:

enter image description here

I searched for my problem, and most solutions suggested to add "type": "module" to manifest.json:

  "background": {
    "service_worker": "background.js",
    "type": "module"
  },

I did that and I got a new very vague error message:

An unknown error occurred when fetching the script.

I tried replacing the import with a require:

const store = require('./testImport');
console.log("Hello Service Worker.")

But these results in another error:

Uncaught ReferenceError: require is not defined

Anyway, I don't think require is the solution anyway. Import statements should work, as I've seen them used by others within service worker files and it worked for them. The problem is there are quite a few resources on the internet on this issue and I feel I've exhuasted them all.

Why don't import statements work in my service worker file? Am I doing something wrong?

UPDATE

@wOxxOm's suggestion to add ./ and .js when importing other JS modules works!

However, I need to import NPM packages into the service worker, and I get this error:

Uncaught TypeError: Failed to resolve module specifier "axios". Relative references must start with either "/", "./", or "../"

package.json

{
  "name": "app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@reduxjs/toolkit": "^1.8.3",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.11.41",
    "@types/react": "^18.0.14",
    "@types/react-dom": "^18.0.5",
    "axios": "^0.27.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^8.0.2",
    "react-scripts": "5.0.1",
    "react-scroll": "^1.8.7",
    "typescript": "^4.7.4",
    "watch": "^1.0.2",
    "web-vitals": "^2.1.4",
    "webext-redux": "^2.1.9"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "INLINE_RUNTIME_CHUNK=false react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "watch": "watch 'npm run build' src"
  },
  "watch": {
    "build": "src/"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@types/chrome": "0.0.193",
    "@types/react-scroll": "^1.8.3",
    "autoprefixer": "^10.4.7",
    "npm-watch": "^0.11.0",
    "postcss": "^8.4.14",
    "tailwindcss": "^3.1.3"
  }
}
  • To use native `import` you need both the path `./` and the file extension `.js`. To use `require` you need to build your project with webpack or a similar tool. – wOxxOm Jul 17 '22 at 12:19
  • @wOxxOm This solved the issue partially! Now I can import files by including `.js`. But I still have issues when trying to import an NPM package. For instance, when trying to import `axios`, like this import axios from `axios`, I get the following error: `Uncaught TypeError: Failed to resolve module specifier "axios". Relative references must start with either "/", "./", or "../".` How could I fix this? – Alexandru Robert Jul 17 '22 at 12:54
  • There's something wrong with your webpack config or package.json or node_modules. Anyway, I doubt axios works in a service worker because it's probably using XMLHttpRequest not `fetch`. – wOxxOm Jul 17 '22 at 13:20
  • @wOxxOm I edited my post and pasted the package,json file. my post I see, but I re-created the react app using the standard `npx create-react-app my-app` command and still get the same exact error. One idea that I might use as a last resort is to manually setup a react project with webpacker, instead of browserlist, as I noticed that for some reason this is the most popular choice for chrome extensions. I gave axios as an example. What I actually want to use is `webext-redux`, and I'm getting desperate as I seem to be unable to make it work :) – Alexandru Robert Jul 17 '22 at 13:50
  • The problem seems to be in your react app config. You need to make an entry for the background script so that it's compiled properly. Currently it looks like the file is not being compiled at all. And you should probably list the browsers explicitly in production for browserlist because extensions can't run in IE/mobile and whatever other browsers in browserlist. – wOxxOm Jul 17 '22 at 14:39
  • The background script is placed in the public folder, where also is the manifest.json. So it gets compiled and builded when I run `npm run build`. Now I don't know if it's an issue that it is in the public folder and it rather should be placed in the src and add an entry as you said in package.json. – Alexandru Robert Jul 17 '22 at 15:51
  • Have you ever tried to integrate redux within a chrome extension? Or have you ever tried to work with react and chrome extensions? Have you ever tried to import a npm dependencie in the background script? Maybe you have a github repo that could help me as a good model? :) – Alexandru Robert Jul 17 '22 at 15:53
  • `public` folder is for stuff to be copied, not compiled, usually. I don't work with react. – wOxxOm Jul 17 '22 at 20:08

1 Answers1

0

When you run npm command. NPM replace package name to real path.
You need to just find real path so that chrome browser will find it.
Real path like this:

/node_modules/pkg-name/dist/main.js

Method 1.
Create path.js file and add this line.

const fullPath = await import.meta.resolve("package_name");
const path = fullPath?.match(/(\/node_modules.*)/)[0];
console.log(path);

then add this line inside scripts in package.json and run npm run path.
"path": "node --experimental-import-meta-resolve path.js",
copy console output text. Replace package name with this copied path.

Method 2
Install other npm package to find and replace
npm packages' virtual path to real path so that chrome browser will find it.
Install Path-fixxer
Add this line in path.js

import setAllPkgPath from "path-fixxer";
setAllPkgPath();

then run command : npm run path.
Now open browser to test it.

Note: It only work with esm npm packages.

Anil kumar
  • 1,216
  • 4
  • 12