How To Build a Chrome Extension Using React

Rate this content
Bookmark
Slides

Last year, as part of my work at Bloomberg, I was tasked with building a Chrome Extension, and persuaded my team to let me build the extension in React instead of vanilla JavaScript. This had several advantages, such as making the code more maintainable and easier to understand, as well as enabling us to use a pre-existing component library for consistent styling across the company, reducing the amount of CSS code we had to write. In my presentation, I will show you a sample Chrome Extension for personal use that I built using React and Material UI that auto-responds to emails sent in Gmail and allows you to take notes regarding the conversation. I will also share steps to build your own Chrome Extension using React, and lessons learned along the way!

FAQ

The Email Postponer Chrome extension is a custom-built tool designed to automatically respond to emails in Gmail based on user input and allow users to add private notes to their emails. It opens as a side panel within Gmail and utilizes Material UI for styling.

React was chosen to build the Chrome extension because it makes the code more understandable and maintainable. Additionally, it allows for easier styling with Bloomberg-specific React components.

The Email Postponer extension interacts with Gmail by opening as a side panel within the Gmail interface. It uses content scripts to manipulate web page content and communicate with a background service worker for executing background tasks and messaging.

To set up a Chrome extension in React, start by creating a new project using Create React App in TypeScript. Modify the build command to generate separate JavaScript and HTML files, adjust settings to avoid source map generation, and ensure correct structuring of the manifest.json file. Install necessary types for using the Chrome API.

To run a Chrome extension locally, build the extension to create a build folder, enable developer mode in Chrome's Manage Extensions settings, and use the 'Load Unpacked' option to select the build folder. Refresh the pages where the extension should run, or open them after loading the extension.

The main difference between Chrome extensions and Firefox add-ons lies in the background processing; Firefox uses background scripts while Chrome uses service workers. Additionally, while both use manifest version 3, specific API namespaces and loading processes differ.

To convert a Chrome extension to a Firefox add-on, adjust the manifest.json file to accommodate Firefox's use of background scripts instead of service workers. Load the extension in Firefox through the 'About Debugging' page by selecting any file within the build folder under 'Load Temporary Add-on'.

Key functionalities of the Email Postponer extension include automatic email responses based on user settings, the ability to add private notes to emails, copying text from the browser, auto-clicking buttons on web pages, and making external service calls through the Fetch API managed by service workers.

Adina Stoica
Adina Stoica
18 min
06 Jun, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

This Talk is about building a Chrome extension using React. It covers the setup, permissions, and behaviors of the extension, as well as calling external services and running the extension locally. The Talk also discusses the process of publishing the extension and includes a demo of an email management system. Overall, it provides a comprehensive overview of building and deploying a Chrome extension using React.

1. Introduction and Overview

Short description:

This part introduces the speaker and the topic of the talk, which is building a Chrome extension using React. The speaker shares their background and experience, as well as the purpose of the extension they built. They mention the features of the extension and their plan to discuss the steps to build a Chrome extension using React. They also mention briefly touching upon Firefox add-ons and compatibility.

Hi everyone, and thank you for tuning in. Also, a big thank you to the conference committee for accepting my talk here. My talk is about how to build a Chrome extension using React.

A little bit about me. My name is Adina. I am a full-stack software engineer at Bloomberg in the HR engineering team, where I focus primarily on front-end items. I am originally from Romania, but I have been in the United States for almost half of my life. I currently live in New York City with my husband and my dog, and my dog's name is Stacks and it's important because we'll be responding to a few emails that Stacks often receives in his inbox and which he might wish to postpone.

Last year, as part of my work at Bloomberg, I was tasked with building a Chrome extension. We decided to build the extension in React instead of vanilla JavaScript, as that would make the code more understandable and maintainable, as well as easier to style by using Bloomberg-specific React components. In this presentation, I will show you a sample extension that I dubbed Email Postponer, that I built specifically to demo here. This extension auto-responds to emails sent in Gmail based on user input, as well as allows users to add private notes to their emails. I will also share steps to build your own Chrome extension using React and lessons learned along the way. I will also briefly touch upon Firefox add-ons and the compatibility between the two.

2. Extension Overview and Setup

Short description:

This part provides an overview of the Email Postponer extension, including its features and how it interacts with Chrome. It explains the steps to set up the extension using Create React app and TypeScript, as well as the use of the Chrome API. The extension uses a manifest.json file and follows manifest version 3. It also discusses the role of the service worker and content scripts in the extension's functionality. The content scripts enable communication between the React code and the background script, and the extension is designed to open as a side panel on Gmail. The section concludes by mentioning the need to add web accessible resources to the extension.

For the agenda, I will start by giving an overview of the extension that I built to demo here, then explain the steps to set up an extension in React, highlight some interesting capabilities that I gave the Email Postponer extension, talk about running the extension locally, as well as publishing it to the store.

Then I will briefly touch upon cross-browser compatibility and how to convert a Chrome extension into a Firefox add-on. And I will end by showing a demo video of the Email Postponer extension in action.

So, for an overview, the Email Postponer extension looks like a web page, as you can see on the right, only opens on Gmail, opens as a side panel instead of a pop-up, because we want to be able to select information in the website without the pop-up closing, leverages Material UI for easy out-of-the-box component styling that is consistent with Google's Material design, allows users to interact with the contents of the web page both manually and automatically, and communicates with the back-end service using the Fetch API.

To set up the extension, I first created a new project using the Create React app in TypeScript. Then I had to change the build command to get React to generate separate JavaScript and HTML files in order to prevent content security policy errors. I also set it so that it doesn't generate source maps to get rid of some extra warnings. Because we are using TypeScript, I had to install some extra types to use the Chrome API. The project uses the Chrome API to interact with Chrome by using an injected object which is also called Chrome.

Create React app creates a manifest.json file for us, but extensions require a specific structure to that. Every extension needs to have a manifest.json file and it needs to be named manifest.json in its root directory. Google is in the process of phasing out manifest version 2 though they just announced some delays on this at Google I/O. Nevertheless, we're using manifest version 3 in our email postponer extension.

Because we want to open the extension as a side panel, we want to make sure action is empty here. Our extension will take its context from an index.html file that is compiled from React. The service worker which is also colloquially referred to as a background script, though there are some differences between the two. It runs on all tabs in the browser and gets executed on browser launch. It listens to specific events in the background, such as changing tabs or updating URLs. It takes browser-level actions accordingly, and it communicates with extension code and content scripts through message passing. This script is one of two scripts written in vanilla JavaScript, and we use it to open and close the site panel, as well as to call the res service using the fetch API, since calling it from React would give us cross-origin resource sharing errors.

Content scripts are scripts that run in the context of web pages, and they have access to DOM elements, objects, and methods. Separate instances run in separate tabs, one instance per tab, and they execute on pages that match the match's regular expression, and they communicate with the service worker and React code through message passing. Content scripts, which we only have one in this extension, are also written in vanilla JavaScript, and we use ours to create a side panel, iframe, pass messages between the React code and the background script, as well as copy and paste selected text in the extension. Also, the extension opens only in Gmail, since Gmail is the only expression that matches the regular expression in the matches property.

These are a few of the ways that messages are passed in extensions. Content scripts sit in the middle between the React code and the background script. React code communicates with content scripts through message passing. Content scripts either take action on the webpage the extension is running on or pass messages to the background script, which then can take browser lever actions accordingly. The background script can communicate with React code directly as well as with content scripts, also through message passing. Since we are running the extension in a side panel instead of a pop-up, we need to add web accessible resources to the extension.