You have 2 free member-only stories left this month.
How To Create A Google Chrome Extension With React
Let’s take a look at how we can create a popup Google Chrome extension using React, TypeScript and craco npm package
What will be covered in this story:
- 1. What are the extensions?
- 2. Create React app
- 3. Manifest.json file
- 4. Popup width and height restrictions
- 5. Retrieving active tab’s URL
- 6. Manipulating DOM content (content scripts)
- 7. Overriding Create React App configuration
If you don't know what is the best solution for you, you can check here:
In this story, we will be creating a popup extension, but you can check about other types: popup, tooltip, omnibox, and context menu. To know more you can check this link :
2. Create React app
We will start from a TypeScript React project created with the use of the create-react-app
CLI command:
npx create-react-app my-app --template typescript
⚠️ NOTE: If you will face any issues with a project you can use my current project configuration as a reference: package.json, tsconfig.json, and yarn.lock files.
yarn add @types/chrome -D
This is all that we need to create your first Chrome extension, let’s do that…
3. Manifest.json file
To make our extension work we will need to update manifest.json
file in the /public
folder:
default_popup
is telling where to find our main HTML file:
default_title
is telling what text user will see when he will hover on our extension’s icon:
⚠️ NOTE: By default, Create React App embeds a small runtime script into index.html
during the production build, this is to reduce the number of HTTP requests. But unfortunately, you will see console errors related to CSP. You could turn off the embedding behavior by setting the INLINE_RUNTIME_CHUNK
flag to false
.
You can add INLINE_RUNTIME_CHUNK
to your .env
file or just place it before the build script:
INLINE_RUNTIME_CHUNK=false
Or add content_security_policy
to the manifest.json
file:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
Now, after updating manifest.json
file, we can run yarn run build
script. When script will finish → new /build
folder will be created at the root of our current project:
Next, we will need to tell Chrome where to find our new extension. You can type this in a new Chrome Tab for opening the extensions menu:
chrome://extensions/
You will need to select a project’s /build
folder:
⚠️ NOTE: After updating/saving your code and rebuilding it → you can just click on Update
(that will update all your extensions):
Or you can update only the required extension:
Let’s take a look at how our first extension will look like:
4. Popup width and height restrictions
As you saw on a previous screenshot our extension doesn’t look so good. We will need to set the width
and height
CSS properties in the index.css
file. Let’s set those values to 1000px
:
Save → Rebuild → Update:
Hm, it doesn't look like 1000px * 1000px… What’s wrong?
⚠️ NOTE: Max width
of Chrome popup extensions can be 800px
and height
is 600px
5. Retrieving active tab’s URL
Let’s take a look at how we can retrieve an URL address from the active tab (where you open your extension). For this, we will need to add permissions
to the manifest.json
file :
"permissions": [
"activeTab"
]
Now we will add a useEffect
hook to our App.tsx
file:
Save → Rebuild → Update extension (look much better):
6. Manipulating DOM content (content scripts)
Before we will talk about the content script, let’s take a look at what we will be implementing (gif):
The only way to get access to the DOM of the page is to use content scripts
:
Content scripts are files that run in the context of web pages. By using the standard Document Object Model (DOM), they are able to read details of the web pages the browser visits, make changes to them and pass information to their parent extension.
We can’t access to the content.js
file directly, but we can communicate with it by using Message Passing.
⚠️ NOTE: We will need to add our content.js
file to the manifest.json
file, we will cover that in a few seconds.
⚠️ NOTE: You will need to add optional_permissions
to the manifest.json
file too :
"optional_permissions": [
"<all_urls>"
]
Adding a content script file to our project
You can place content script
at your /public
folder directly…
…but we will not do that, because we will not have all TypeScript features available.
We will put our content script to the /src/chrome/content.js
:
We will update manifest.json
file soon…
After that, we will update our App.tsx
file. When the user will click on a button → message will be sent to the content script
:
⚠️ NOTE: Webpack will bundle all our React app scripts into one JS bundle, but we want our content.ts
file to be converted to content.js
and put it to the static/js/content.js
:
…so we could point to it in our manifest.json
file:
How can we do that?
6. Overriding Create React App configuration
We will need to override some Create React App configuration and we can do that by using craco npm
package (Create React App Configuration Override):
yarn add @craco/craco
Add craco.config.js
configuration file to the root of our project:
And update “build” script:
Let’s run yarn run build
script and see what we’ll get:
Awesome 🎉 Now we can add our content script to our manifest.json
file, so it would look like this:
Save → Rebuild app → Update extension (gif):
🆘 Sometimes you could get such error:
Try to disable all your chrome extensions one-by-one and restart the chrome browser:
If you liked this story you can check “List of all my stories” as well. Happy coding!