YTII Official Blog - Stories, Updates and Tips

How to Create a Chrome Extension With ReactJS?

Written by Mangesh Gothankar | March 28, 2023 10:09:48 AM Z

Note: This blog was originally published on 7th October 2021 and updated on 14th March 2023.

Quick Summary: In this post, we will guide you seamlessly through the process of creating a Chrome extension with reactjs. By the end of this guide, you will be able to build your own extension functionality. So, without further ado,  let’s get started. 

What are the Extensions? 

Small software programs that personalize the browsing experience, giving users the freedom to tailor the behavior and Chrome functionality keeping in mind the needs of the individual. Extensions are developed on different web technologies, including CSS, JS, and HTML. The purpose of having an extension is to make everything easy to understand. There are multiple components with different ranges of functionality in a single extension. 

Recommended Read: 15+ Top React Libraries to Try

Key Takeaways
  • Build components that respond to user input using React.js.
  • Test your extension thoroughly using Jest, Enzyme, and Puppeteer.
  • Publish your extension to the Chrome Web Store and follow the developer guidelines.
  • Set up a React.js environment in your Chrome Extension project using tools like create-react-app or react-scripts.

How to Create React App? 

In this step, we will be starting from a TypeScript React project created with the create-react-app CLI command. 

npx create-react-app my-app --template typescript

Update the Manifest.json File 

Now, if we are trying to create our extension work seamlessly, without any interruption, we will have to update the manifest.json file in the /public folder. 

{

  "name": "Hello Extensions",

  "description": "Base Level Extension",

  "version": "1.0",

  "manifest_version": 2,

  "browser_action": {

    "default_popup": "index.html",

    "default_title": "Open the popup"

  },

  "icons": {

    "16": "logo192.png",

    "48": "logo192.png",

    "128": "logo192.png"

  }

}

Default_popup will help us know how to find out the main HTML file. 

Default_title helps us know what text the user will be shown when they hover on the extension icon. 

Create React App, by default, embeds the small runtime script into index.html during the production build. Further, it minimizes the number of HTTP requests. There is a high possibility that you are going to witness console errors related to CSP. Besides, you can even turn off the embedding behavior. For that, all you need to do is set the inline_runtime_chunk flag to false. Also, you can add inline_runtime_chunk to your .env file or even add it before the build script. 

INLINE_RUNTIME_CHUNK=false

Alternatively, you can try adding content_security_policy to the manifest.json file. 

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Once the manifest.json file is updated, it is time to run the yarn run build script. And, once that is finished, a new build folder is created at the root of the project. 

After that, we just need to inform Chrome how and where to find the new extension. For that, we need to type in the Chrome Tab the following for opening the extension menu:

chrome://extensions/

Now, we will be selecting the /build folder of the project.

(Once you have updated/saved the code, click on Update to update all the extensions used.)

Check out the difference between Reactjs, angularjs and vuejs.

Popup Width and Height Restrictions in Chrome extension with Reactjs 

We have created the extension until this step, but it might not look as good as we want. Hence, we will have to set the height and width of the CSS properties in the index.css file. And then save, rebuild, and update. 

For the width and height of the extensions, you need to make them 800px and 600px, respectively. 

How to Retrieve the Active Tab’s URL? 

For this, we will have to add permissions to the manifest.json file. 

"permissions": [

"activeTab"

]

After that is done, we will add useEffect hook to the App.tsx file. 

import React, { useEffect, useState } from 'react';

import logo from './logo.svg';

import './App.css';

export const App = () => {

    const [url, setUrl] = useState('');

    /**

     * Get current URL

     */

    useEffect(() => {

        const queryInfo = {active: true, lastFocusedWindow: true};

        chrome.tabs && chrome.tabs.query(queryInfo, tabs => {

            const url = tabs[0].url;

            setUrl(url);

        });

    }, []);

    return (

URL:

                    {url}

    );

};

Now, you can save, rebuild, and update the extension to achieve the final look we want. 

DOM Content Manipulation (Content Scripts)

So, we need to use the Content Scripts to access the DOM of the page. So, what are the content scripts? Well, these are the files that run in the context of web pages. When the DOM is used, it helps read every detail about the web pages the browser visits. Besides, it can even make changes to them and even pass essential information to the parent extension. 

However, we will not be able to access the content.js file directly. We need to use Message Passing for that. 

  • Add content.js file to manifest.json file
  • Add optional_permissions to manifest.json file 

"optional_permissions": [

 ""

]

Recommended Read: 15 Advantages of ReactJS for Application Development

Adding Content Script File to the Project 

Now is the time to place the content script in the /public folder directly. However, we can’t really do that because we don’t have all the TypeScript features that we need. 

So, for that, we need to place the content script to the /src/chrome/content.js

import { ChromeMessage, Sender } from "../types";

const messagesFromReactAppListener = (message: ChromeMessage, sender, response) => {

    console.log('[content.js]. Message received', {

        message,

        sender,

    })

    if (

        sender.id === chrome.runtime.id &&

        message.from === Sender.React &&

        message.message === 'Hello from React') {

        response('Hello from content.js');

    }

    if (

        sender.id === chrome.runtime.id &&

        message.from === Sender.React &&

        message.message === "delete logo") {

        const logo = document.getElementById('hplogo');

        logo.parentElement.removeChild(logo)

    }

}

/**

 * Fired when a message is sent from either an extension process or a content script.

 */

chrome.runtime.onMessage.addListener(messagesFromReactAppListener);

Now, we will update the manifest.json file and, after that App.tsx file. So, when the user clicks on the button, they are redirected to the content script. 

import React, { useEffect, useState } from 'react';

import logo from './logo.svg';

import { ChromeMessage, Sender } from "./types";

import './App.css';

export const App = () => {

    const [url, setUrl] = useState('');

    const [responseFromContent, setResponseFromContent] = useState('');

    /**

     * Get current URL

     */

    useEffect(() => {

        const queryInfo = {active: true, lastFocusedWindow: true};

        chrome.tabs && chrome.tabs.query(queryInfo, tabs => {

            const url = tabs[0].url;

            setUrl(url);

        });

    }, []);

    /**

     * Send message to the content script

     */

    const sendTestMessage = () => {

        const message: ChromeMessage = {

            from: Sender.React,

            message: "Hello from React",

        }

        const queryInfo: chrome.tabs.QueryInfo = {

            active: true,

            currentWindow: true

        };

        /**

         * We can't use "chrome.runtime.sendMessage" for sending messages from React.

         * For sending messages from React we need to specify which tab to send it to.

         */

        chrome.tabs && chrome.tabs.query(queryInfo, tabs => {

            const currentTabId = tabs[0].id;

            /**

             * Sends a single message to the content script(s) in the specified tab,

             * with an optional callback to run when a response is sent back.

             *

             * The runtime.onMessage event is fired in each content script running

             * in the specified tab for the current extension.

             */

            chrome.tabs.sendMessage(

                currentTabId,

                message,

                (response) => {

                    setResponseFromContent(response);

                });

        });

    };

    const sendRemoveMessage = () => {

        const message: ChromeMessage = {

            from: Sender.React,

            message: "delete logo",

        }

        const queryInfo: chrome.tabs.QueryInfo = {

            active: true,

            currentWindow: true

        };

        chrome.tabs && chrome.tabs.query(queryInfo, tabs => {

            const currentTabId = tabs[0].id;

            chrome.tabs.sendMessage(

                currentTabId,

                message,

                (response) => {

                    setResponseFromContent(response);

                });

        });

    };

    return (

URL:

                    {url}

 

                

                

 

Response from content:

                    {responseFromContent}

    );

};

With the Webpack, we can bundle all the React app scripts into one bundle. We will convert the content.ts file to content.js before placing it in static/js/content.js and pointing it to the manifest.json file. 

 "content_scripts": [

    {

      "matches": ["http://*/*", "https://*/*"],

      "js": ["./static/js/content.js"],

      "all_frames": false,

      "run_at": "document_end"

    }

  ],

Now, We Will Override Create React App Configuration

It is time now to override Create React App configuration, for which we need to use craco npm package. 

yarn add @craco/craco

Now, we need to add the craco.config.js configuration file to the project’s root. 

module.exports = {

    webpack: {

        configure: (webpackConfig, {env, paths}) => {

            return {

                ...webpackConfig,

                entry: {

                    main: [env === 'development' &&

                    require.resolve('react-dev-utils/webpackHotDevClient'),paths.appIndexJs].filter(Boolean),

                    content: './src/chrome/content.ts',

                },

                output: {

                    ...webpackConfig.output,

                    filename: 'static/js/[name].js',

                },

                optimization: {

                    ...webpackConfig.optimization,

                    runtimeChunk: false,

                }

            }

        },

    }

}

We will be updating the build script now. 

"scripts": {

    "start": "react-scripts start",

    "build": "INLINE_RUNTIME_CHUNK=false craco build",

    "test": "react-scripts test",

    "eject": "react-scripts eject"

  },

After that, we need to run a yarn run build script. 

Great, this is the step to add the content script to our manifest.json file. 

{

  "name": "Hello Extensions",

  "description" : "Hello World",

  "version": "1.0",

  "manifest_version": 2,

  "browser_action": {

    "default_popup": "index.html",

    "default_title": "Open the popup"

  },

  "icons": {

    "16": "logo192.png",

    "48": "logo192.png",

    "128": "logo192.png"

  },

  "content_scripts": [

    {

      "matches": ["http://*/*", "https://*/*"],

      "js": ["./static/js/content.js"],

      "all_frames": false,

      "run_at": "document_end"

    }

  ],

  "permissions": [

    "activeTab"

  ],

  "optional_permissions": [

    ""

  ]

}

Now, just save, rebuild, and update the extension. 

 

Finally, you can disable all the chrome extensions you have installed and restart the browser to ensure everything works fine. 

Conclusion

Congratulations! You have successfully learned how to create a Chrome extension with reactjs. However, don’t forget to disable all Chrome extensions when you are done with all the steps to ensure your newly created extension works fine. 

Need help to hire Reactjs developers in India? At Your Team In India, we have a pool of certified Reactjs engineers. Connect with us our business head now and get a free consultation.

 

Frequently Asked Questions [FAQs]

Q: How do I run React as Chrome extension?

To run React as a Chrome extension, you need to create a new project, set up a React.js environment, configure it to work with the Chrome extension, use Chrome Extension APIs to interact with the user's browsing experience, build your components, and publish your extension to the Chrome Web Store.

Q: Can you use React in chrome extension?

Yes, you can use React in Chrome extensions. Chrome extensions are essentially web applications that run in the browser, and React is a popular JavaScript library for building web interfaces. You can use React to create the user interface of your Chrome extension and interact with the DOM just as you would in a regular web application. Additionally, you can use Chrome Extension APIs to access features and functionality specific to Chrome extensions, such as communication with background scripts or injection of scripts or styles into web pages.

Q: How do I enable React on Google Chrome?

React is a JavaScript library that runs on web pages, so you don't need to enable it specifically on Google Chrome. However, if you want to develop React applications or Chrome extensions using React, you can install the React Developer Tools extension for Google Chrome. Here are the steps to install the React Developer Tools:

  1. Open the Google Chrome browser on your computer.
  2. Go to the Chrome Web Store.
  3. Search for "React Developer Tools" in the search bar at the top left corner of the page.
  4. Click on the "Add to Chrome" button next to the React Developer Tools extension.
  5. A pop-up window will appear asking you to confirm the installation. Click on the "Add extension" button to confirm.
  6. Once the installation is complete, the React Developer Tools icon will appear in the top right corner of your browser.
  7. You can then click on the icon to access the developer tools and start debugging your React applications or Chrome extensions.

By following these steps, you can enable the React Developer Tools on Google Chrome and start developing React applications or Chrome extensions more efficiently.

Q: Does React work on every browser?

React is designed to work on most modern browsers, including Google Chrome, Firefox, Safari, Microsoft Edge, and others. However, the exact level of support can vary depending on the version of the browser and the specific features or APIs used by your React application. React also includes polyfills for older browsers to provide basic compatibility, but some features may not work properly or require additional configuration