Create Chrome Extension in React
Tags: javascript, react, showdev, tutorial
Published: 2020-03-19 11:56:41

When I moved to Edge weeks ago, I found there's no built-in strong password generator in Edge. Then I decide write one for it.

Most of the extensions on marketplace are write many years ago, and they were written in raw HTML, CSS and JavaScript. But we have React and UI component libraries now, life should be easier.

The problem I soon found is there's almost no tutorial for a React extension anywhere. That's why I decide to share everything here. 

* The source code is origin from my side project [10converters.com](https://10converters.com/tools/strong-password-generator). 
* Repo on Github [strong password generator]
 (https://github.com/bayardlouis470/strongpassword). 
* Edge Extension Addons Store: [Strong Password Generator](https://microsoftedge.microsoft.com/addons/detail/kbgpmjeanbjhhnappoclfgcaogkbehad).

Star the repo on Github or leave a review on Edge Addons Store are both welcome!

# Features of the extension

![Strong Password Generator Screenshot](https://dev-to-uploads.s3.amazonaws.com/i/8ltrw07xv7dq82w8q5w2.png)

It generates a 15 characters long password with lowercased letters, uppercased letters, numbers and symbols.

But it won't like Chrome built-in password manager, it doesn't:
* copy to clipboard automatically
* fill in the password/confirm field in web page
* manage/backup your password somewhere, not in cloud, not even do it locally

It does:
* keep everything running in client side, that means no server at all
* manual copy to clipboard

I tried to make it as simple as a one-day-job. Anyone who follows this tutorial could submit your own extension to Chrome Web Store or Microsoft Edge Extension Addons(what a long name) in a single day(but from my experience, Microsoft need 2-3 days to approve your submission).


# Extension Basic

Before dive into the details, I want to explain a little the basic structure of an extension of chromium based browser.

This extension structure works on Chrome, Edge and Brave, and maybe other Chromium based browsers I don't know.

There're several key parts of an extension:

![Strong Password Generator Extension](https://dev-to-uploads.s3.amazonaws.com/i/8ms6nlmnok1xivt1unzg.png)

### manifest

manifest describes what's in the source package. It specified where browser could find background, content script, popup and option pages. As well as it describes permissions required by the extension.

### background

A piece of code which is launched when the extension launched, and won't be terminated until extension removed or browser shutdown.

Background code has access to all chrome APIs, other parts are limited. But background doesn't have an UI and can not access DOM.
 
### popup

The UI which is popped up while user click on 'browser action' which is your extension icon button right to the browser address bar.

Most extensions need a popup as entry.

### options

It's an optional part of the extension. Not all extensions has an options page. It is used as a configuration UI for the extension. Your extension has to provide an entry for it.

If you have some something complicated to be configured, you need this.


### content script

Content script is a piece of JavaScript which runs in a tab with specific URL. the URL pattern is defined in manifest.json. If the URL matched with which is specified in manifest.json, browser will launch the content script. It will be terminated while the URL changed, or tab closed.

If you want to manipulate DOM, you need content script.

So you should already have idea of what these parts are doing now.

### Which parts involved in Strong Password Generator extension

Background, not in this tutorial, but there's an empty background.js in repo, just for future use.

Popup, yes. That's the focus of this article. I will show you how to write a Popup in React + Material.

Options, no.

Content script, no.

# Start from scratch

Here're 5 steps to create an extension in React from scratch.

## Step 1: create a react app

```
$npx create-react-app extension
```

This will create a regular react app. Everything else are growing from this seed app.
 
## Step 2: Modify public/manifest.json


You've already had a public/manifest.json after CRA(create-react-app). Change the file as below:

```
{
    "name": "Strong Password Generator",
    "version": "1.0.0",
    "manifest_version": 2,
    "description": "Strong password generator",
    "icons": {
        "512": "logo512.png"
    },
    "browser_action": {
        "default_icon": "logo512.png",
        "default_popup": "popup.html"
    }
}
```


## Step 3: Create a build script(script/build.sh)

```
#!/bin/bash

build() {
    echo 'building react'

    rm -rf dist/*

    export INLINE_RUNTIME_CHUNK=false
    export GENERATE_SOURCEMAP=false

    react-scripts build

    mkdir -p dist
    cp -r build/* dist

    mv dist/index.html dist/popup.html
}

build
```

There're 2 things did in this script:

* build react app with some specific environment variables set
* renamed index.html into popup.html

INLINE_RUNTIME_CHUNK=false disabled webpack generating inline JavaScript in HTML. Normally webpack will put its own runtime into HTML inline script. But inline script is not allowed by browser extension.

Rename index.html into popup.html because it is required to be popup.html in manifest.json.

After create script/build.sh, don't forget add x permission:
```
chmod +x script/build.sh
```

## Step 4: Modify package.json

modify scripts like below:
```
"scripts": {
    "start": "react-scripts start",
    "build": "./script/build.sh",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
},
```

## Step 5: Build and load into Chrome(or Edge)


```
$npm run build
```

Then you will get a 'dist' directory. Load it as unpacked extension in Chrome or Edge. You would see:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2yud1v1scr0wtikb053s.png)

The React extension is running.


# To be continue

There're still pending issues for a serious extension, like:

* How to handle Options page? It's another page rather than Popup, but CRA created a SPA.
* Is there any performance issue to write extension in React?
* My content script is going to inject some UI component into host pages, can React be applied in this scenario?

And maybe some other topics not related to React too much but still important for a serious extension:

* How to obfuscate source code, especially background.js
* I'm going to introduce Firebase in my extension, any tips?


All the above will be discussed in the next post if someone interests into these questions. Leave a comment below if you have any other questions, suggestions, any feedback are welcome.