0

I'm trying to create a simple Chrome extension: when it's clicked, a small popup is opened that has an Expand button (Popup.js). When an Expand button is clicked, a new tab is opened (Window.js).

However, I can't get it to work.

App.js:

import React from "react";
import Popup from "./Popup";

const App = () => {
  return (
      <div>
        <h1>React Chrome Extension</h1>
        <Popup />
      </div>
  );
};

export default App;

Popup.js

/*global chrome*/
import React from "react";

const Popup = () => {
    const handleExpandClick = () => {
        chrome.tabs.create({
            url: chrome.runtime.getURL("window.html")
        });
    };

    return (
        <div style={{ width: "200px", height: "100px", padding: "20px" }}>
            <button onClick={handleExpandClick}>EXPAND</button>
        </div>
    );
};

export default Popup;

Window.js

/*global chrome*/
import React from "react";

const Window = () => {
    return (
        <div>
            <h1>This is the new window opened by the extension!</h1>
        </div>
    );
};

export default Window;

background.js:

chrome.runtime.onInstalled.addListener(() => {
    console.log("Extension installed!");
});

package.json:

{
  "name": "react-chrome-extension",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "cra-template": "1.2.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-scripts": "5.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "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"
    ]
  }
}

manifest.json:

{
  "manifest_version": 3,
  "name": "React Chrome Extension",
  "version": "1.0",
  "description": "A simple React-based Chrome extension",
  "permissions": ["tabs"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  },
  "host_permissions": [
    "http://*/*",
    "https://*/*"
  ],
  "icons": {
    "16": "favicon.ico",
    "48": "favicon.ico",
    "128": "favicon.ico"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["background.js"]
    }
  ]
}

Directory structure:

enter image description here

The contents of build folder have been copied into public folder:

enter image description here

When I load the extension inside Chrome:

the extension appears on extension bar, but when I click it:

enter image description here

Instead of a popup I get an empty window.

The popup.html and window.html generated during build seem to have empty body:

popup.html:

<!-- public/popup.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Popup</title>
</head>
<body>
<div id="root"></div>
<script src="popup.js"></script>
</body>
</html>

window.html:

<!-- public/window.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Window</title>
</head>
<body>
<div id="root"></div>
<script src="window.js"></script>
</body>
</html>

And there are no window.js or popup.js anywhere in the build folder or its subfolders.

1
  • 1) Your build config is apparently incorrect as it doesn't produce window.js and popup.js. 2) Your files have an uppercase letter, which is a very bad practice since you use a lowercase name in the html so it won't work with a case-sensitive file system in Linux/MacOS and even Windows in some configs 3) background.js should be the background script, not a content script. 4) Note that the popup is a separate window so it has its own separate devtools: right-click inside the popup and select "inspect" in the menu. Commented Dec 7, 2024 at 9:22

1 Answer 1

1

To avoid common issues like this, you can use this GitHub repo chrome-extension-boilerplate-react-vite. It is a good structure Chrome extension code that uses popular technology such as React, Vite, Typescript

If you are new to extension development, it may be a bit difficult to understand the structure of this repo, but once you realize what is going on, you can build any extension.

Sign up to request clarification or add additional context in comments.

1 Comment

You can even use common React libraries to build your extension, such as React Router Dom, Zustand, or Redux for state management, MUI or Shdcn for UI, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.