How To Build a Chrome Extension Using React
AI Generated Video Summary
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
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.
2. Extension Overview and Setup
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.
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.
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.
3. Extension Permissions and Behaviors
The extension code is in the index.html file, and the resources are available on all web pages. We are only using the active tab permission to open and close a side panel. The host permissions grant the extension the ability to send cross-origin resource sharing requests. We create an iframe in the content script that toggles between showing and hiding when receiving a toggle extension message. Extensions will soon be able to use the side panel in Chrome, which greatly improves workflows. We can copy selected text from the browser by querying the active tab and using the dom document get selection method. We can also auto-click buttons on the website by querying the active tab and using the DOMDocumentQuerySelector method.
And there are none by default. The extension code is in the index.html file, and the resources are available on all web pages. The permissions option is similar to permissions on your phone when you are installing an app. We are only using the active tab permission here, which gives an extension temporary access to the currently active tab. We also need this permission to open and close a side panel.
Lastly, the host permissions grant the extension the ability to send cross-origin resource sharing requests to the hosts mentioned in the array. This allows us to make the service calls that allow us to save our notes. Normally, extensions open in a popup, and that closes when it loses focus. Since our extension is a form which we want to complete using text from the website, we need it to stay focused and on. The first step was to make sure that there is no default popup property on the action field in manifest.json. Remember, that was empty in the previous slide. Then, we need an event listener in the service worker for when the extension icon is clicked. We can call this toggle extension. This sends a message to the content script.
In the content script, we need to create an iframe that is not displayed, but whose source is indexed.html. As you can see here, we have an iframe and the source is index.html. And then, we need to add an event listener that flips between showing and hiding the iframe when receiving a toggle extension message. It is worth mentioning that at the Google I/O conference a few days ago, the speaker mentioned extensions will soon be able to use the side panel in Chrome. The side panel API is an upcoming Manifest version three feature that isn't yet widely available. And it will behave a bit differently than what I described here. But it will greatly improve workflows, at least in Chrome.
One of the behaviors I want to highlight is copying selected text in the browser. To copy selected text from the browser, we need to query the current active tab in the current window, and send a message to the content script. When the content script receives the message, it just uses the dom document get selection method to get the text, and then it sends it back to the caller. Be sure to remove ranges to ensure predictable behavior as not using it works fine for me on Windows, but not on Mac.
The other behavior that I want to highlight is auto-clicking buttons in the website that the extension is running on. To auto-click buttons in the browser, we need to query the current active tab in the current window, and then send a message to the content script. When the content script receives the message, it just uses the DOMDocumentQuerySelector method with a selector for the button you want to automatically click in order to get a button element. And then, it just calls the click method on the button element. Our response is sent back to the caller based on whether or not the operations were successful.
4. Calling External Services
We call external services using the Fetch API. Only the service worker can call the Fetch API without course errors. We pass messages from the extension code to the content script and then relay those messages to the background script. We use a helper function called selfSendRequest to send and handle the messages. In the background script, we use the Fetch API to make requests and send the response or error back to the caller.
The last behavior I want to highlight is calling external services. We call external services using the Fetch API. An important caveat is that only the service worker can call the Fetch api without course errors. So, we need to pass messages from extension code to the content script, which is the only one that the extension code can pass messages to. And then, relay those messages to the background script. I wrote a helper function called selfSendRequest that sends the message to the content script and then either rejects the response if it's an error or resolves it to the response. We can then call this method asynchronously with our request details. In the background script, we just call a standard Fetch API with a given request and then send the response or an error back to the caller depending on whether the fetch request was successful.
5. Running the Extension Locally
So the next thing I want to talk about is running the extension locally. To run the extension locally, you first need to build the extension, which will create the build folder for you. Then you can go to Manage Extensions, turn on developer mode, and load Unpacked. You need to select the build folder to load the extension. And you need to make sure to refresh the pages that the extension should be running on after the update. Or preferably not have them open when loading the extension.
I have a video to show you how to do this. So you go to Manage Extensions, which takes you to that URL. And then you can turn on developer mode, load Unpacked. Make sure to select the build folder. And then your extension's right there. So now you can navigate to Gmail in our case. And you can pin the extension on the top right. Pin the extension on the top right. And then you can click to open and close it.
If you have an extension in Chrome, you can convert it to a Firefox add-on relatively easily. Both Chrome and Firefox are currently running Manifest Version 3. However, Firefox hasn't adopted Service Workers and still uses background scripts. This means that your Manifest.json file will differ, at least in the background line. And since neither Chrome nor Firefox allow a different name for the manifest file, you must have a different version of the extension for each browser, even if everything else is compatible.
To publish to the Chrome Web Store, you need a developer account and a zip file of your build folder. You can upload the extension to the Chrome developer dashboard.
6. Publishing, Demo, and Conclusion
Before publishing the Chrome extension, it undergoes a review process. The same applies to Firefox add-ons, which also require a review. The demo showcases an email management system with features like email postponement and note-taking. Tex responds to emails, adds notes, and generates new emails. The presentation concludes with available resources and an invitation to connect on LinkedIn or Twitter.
Before it becomes available, the Chrome extension will undergo a review process. More details at that link. To publish a Firefox add-on, you also need a developer account for Firefox in this case. You will also need a zip file of your build folder or any of the other accepted package types. When you upload the extension, it undergoes automatic validation. After it passes validation, you can submit the extension for publishing. Firefox add-ons are available immediately after upload. However, they will also undergo a review process and they might be blocked later.
And this is my demo. For the demo, Tex has received a bunch of emails. Let's check this email. This is an email that Tex has responded to. He requested a postponement. These are the notes that he added. The first one is generated automatically, with the text of the email that he responded. He can add new notes. Now, let's see a new email. Random company wants to talk to Tex. He might respond to Adena, who works at Random Company. And I missed the Y, so Random Company. And give a timeline, it's the beginning of August. Figure out what time of the day it is, and then you can generate an email. Check the email content, and then it can be automatically sent. It appears in the notes. And more notes can be added here. Very slowly. Yes, and this is my presentation, this is my demo. If you want to read more about the tech used in this talk, this is a list of helpful resources. The slides will be made available to you. And thank you so much for listening to my talk. You can connect with me on LinkedIn or Twitter at adinotech21.