Create a Google Chrome Extension using React
Tags: chrome, react, browser, extension
Published: 2021-08-12 10:01:35

You're probably here because you just realized that a chrome extension written in Vanilla JavaScript is not fulfilling your needs and you miss working in a React-like technology. So, without wasting any of your time, let's dive straight into the steps of creating a Google Chrome extension using REACT.

**Note:** In order to keep this post short and precise, the terms related to chrome extension are not explained in detail. Wherever felt necessary, links to appropriate resources are included so that you can further read about that topic. Also, brief explanation of 2 things is also given at the bottom of this post so that you can develop a better understanding of how this extension works.

##<center>Steps to Create a Google Chrome Extension using REACT</center>
<br/><br/>
#1. Create an empty folder
Navigate to the place where you want to store your extension locally and create a new folder. You can name it whatever you want.
#2. Initialize 'npm'
Go inside that newly created folder, open a terminal and run the following:

```bash
npm init
``` 

(Keep pressing Enter 😅)
Once done, we now need to install some [dev dependencies](https://medium.com/@dylanavery720/npmmmm-1-dev-dependencies-dependencies-8931c2583b0c).
#3. Install required dev dependencies
Run the following command. It will install all the space-separated packages as dev dependencies.

```bash
npm i -D babel-core babel-plugin-transform-runtime babel-polyfill babel-preset-env clang-format parcel-bundler
```
#4. Install react dependencies
As we want to create a React App, we need to install 'react' and 'react-dom'
So, run the following:

```bash
npm i -s react react-dom
```

We now have our required packages installed
#5. Create a folder for source files
Create a folder (let's call it 'src') to place all your files (before the parcel build process. Explanation about Parcel build is given at the bottom of this post).
The files that you will create in this folder will be the ones that you interact with
#6. Create 'manifest.json' file
Create a file named 'manifest.json' inside the newly created 'src' folder. 
Add some boilerplate code for a simple chrome extension

Code to get you started:

```json
{
  "name": "My awesome extension",
  "version": "0.0.0",
  "description": "This is an awesome extension",
  "manifest_version": 2,
  "browser_action": {
    "default_popup": "popup.html"
  }
}
```
#7. Create a React Component
Create a file for a test React Component (let's call it 'Dummy').
So, create a file 'Dummy.js' inside the 'src' folder.
#8. Write code for the React Component
You can use the following code to test your 'Dummy' component

```react
import React from 'react';
const Dummy = () => {
  return (
    <React.Fragment>
      <h1>
        Hello from Dummy
      </h1>
    </React.Fragment>
  );
}

export default Dummy;
```
#9. Create 'popup.html' file
Create a 'popup.html' file (you can name it whatever you like) inside 'src' folder and add the boilerplate HTML code inside it. This is the front-end page of your extension when it is clicked. The name of this file should be the same in 'manifest.json' where 'default_popup' is mentioned.
#10. Create 'popup.js' file
Create a file 'popup.js' inside 'src' folder (again, you can name it anything you like).
#11. Connect 'popup.js' with 'popup.html'
Add a 'script' tag pointing to the file created in the previous step inside the 'popup.html' file. In this case, the name of the file is 'popup.js'. <br/>
##IMPORTANT NOTE:
**DO NOT** give it a *'type'* attribute of *'module'*. This will lead to an error afterwards.
#12. Import required packages in 'popup.js'
Import the 'Dummy' component, 'react' and 'react-dom' packages inside 'popup.js'.

```react
import Dummy from './Dummy';
import React from 'react';
import ReactDOM from 'react-dom';
```

#13. Create a target 'div' tag to render our react code
Create a `div` tag inside 'popup.html' to render your React component. Give it an id `app`. (Again, you can name it anything) 

```HTML
<div id="app"> </div>
```

This is where our 'Dummy' component is going to be rendered.
#14. Write code to render 'Dummy' component
Write the following line inside 'popup.js' to render the Dummy React component inside the 'div' tag with id 'app' in 'popup.html'.

```react
ReactDOM.render(<Dummy />, document.getElementById('app'));
```
#15. Create bash scripts
Now, we move to write the bash scripts in the 'package.json' file. So that when we want to create extension files that are understood by the browser, we can simply run those scripts.
Copy the following code into 'package.json' file.

```json
"scripts": {
  "copy": "cp src/manifest.json dist/ && cp src/popup.html dist/",
  "build": "parcel build src/popup.js -d dist/ -o popup --no-minify && npm run copy"
}
```
**Note:** Explanation of these scripts is at the end of this post
#16. Build the extension code
Now go to the terminal and run 

```bash
yarn build
```

You will see the 'dist' folder being created inside your extension directory/folder
#17. Loading the extension files
[Load](https://webkul.com/blog/how-to-install-the-unpacked-extension-in-chrome/) this 'dist' folder in the extensions section on the browser and Enjoy 🙂

#BONUS: 
I understand that this was a lot of information bombarded at you all at once, so if you want to gain a deeper insight into how this code works, you can continue reading this post.

#1. Parcel Build Process
[Parcel](https://parceljs.org/) is a web application bundler that translates your code files in such a way that a browser can easily run it. And in the case of extension, we want to `import` packages in our `react` code and also `export` them to be used in other components. 
But this is not directly possible in the case of extensions (at the time of writing this post). So, we need some helping tool, that helps us. And this is where parcel comes to our rescue.

Parcel takes the target file (in this case 'popup.js') and translates that file. And in the file translation, it encounters the imported packages too. So, it will translate their code as well and continue to do so until all the required packages' code is translated and placed into a single file.
Now, this single file can be easily read and understood by the browser. 
So, how do we create this single file?
Well, this is explained below in the script explanation.
#2. Scripts explanation

```json
"scripts": {
  "copy": "cp src/manifest.json dist/ && cp src/popup.html dist/",
  "build": "parcel build src/popup.js -d dist/ -o popup --no-minify && npm run copy"
}
```

These are the scripts that we will be using in our extension development. Let's understand how they work

##Copy Script
```json
"copy": "cp src/manifest.json dist/ && cp src/popup.html dist/"
```
This script is written to allow the developer to copy (only copy, not the parcel build) 'manifest.json' and 'popup.html' files from our 'src' folder to the 'dist' folder. 
You can edit this script to include more files as well. 
Whenever you have files that do not contain any special task (like import, export, etc.) then you should directly copy it into the final extension code folder (in this case 'dist' folder).

##Build Script
```json
"build": "parcel build src/popup.js -d dist/ -o popup --no-minify && npm run copy"
```
If you understood the previous script explanation, then this will also be easy for you.
This script tells the 'parcel' bundler to 'build' (or translate) our 'popup.js' file along with all the imported package code that is used inside 'popup.js' file and place it inside the 'dist' folder. And after the build process, run the 'copy' script as well. (You can take out this part if you don't want to run the 'copy' script every time you build your 'popup.js' file.)
#How to use these scripts?
Whenever you want to copy or build the extension code, go to the terminal and write one of the following

```bash
yarn copy
```

```bash
yarn build
```
You can also use 'npm' instead of 'yarn' for running these scripts.

That's it for this post. Don't forget to like this post if it helped you in any way.

Also, do share your thoughts in the comments. And, if you found any error, feel free to point it out in the comments.
Thank you 🙂.