Wrestling with Create React App feels like trying to teach a cat to swim. Let's sprinkle some fun into this tussle and configure it for a Chrome extension β because, why not add some spice to the mix?
TL;DR
Uncover the systematic process for configuring Create React App to seamlessly generate Chrome Extensions Manifest V3.
Introduction
This guide presumes a fundamental understanding of Chrome Extension development, allowing us to focus on generating a structure that encompasses the majority of features:
Structure
While HTML templates for the Background and Content script are unnecessary (being scripts in the Chrome Extension ecosystem), we will maintain a consistent structure. Also Devtools carries less significance here, but we'll incorporate it to demonstrate how to set up key features.
The main component here is the Popup, where we position our primary React app:
Manifest.json
Manifest.json serves as the cornerstone file in the Chrome extension ecosystem. It informs the Chrome extension ecosystem about our intentions to connect the popup, background scripts, and dev tools:
{"manifest_version": 3,"name": "React Typescript Chrome Extension Boilerplate","version": "0.0.1","description": "Working React TypeScript boilerplate for a Chrome extension using Create React App.","background": { "service_worker": "background.bundle.js" },"action": {"default_popup": "./index.html","default_icon": "logo-34.png"},"icons": {"128": "logo-128.png"},"content_scripts": [{"matches": ["http://localhost:8000/*"],"js": ["content.bundle.js"]}],"devtools_page": "devtools.html","web_accessible_resources": [{"resources": ["logo-128.png", "logo-34.png"],"matches": []}],"content_security_policy": {"extension_pages": "script-src 'self'; object-src 'self'"},"permissions": ["storage", "contextMenus", "scripting", "tabs"],"host_permissions": ["http://localhost:8000/"]}
With that, our next task is to modify the React Create App Webpack.
Webpack
We'll leverage react-app-rewired for this purpose.
It assists in adjusting the create-react-app webpack config without the need to 'eject'.
We'll add a couple of scripts in package.json
:
"start": "react-app-rewired start","build": "BUILD_PATH=build react-app-rewired build"
Furthermore, we need to create a config-overrides.js
file where we configure the structure.
const path = require("path");const HtmlWebpackPlugin = require("html-webpack-plugin");const webpack = require("webpack");const CopyWebpackPlugin = require("copy-webpack-plugin");const pagesNames = ["Background", "Content", "Devtools"];const CHROME_EXTENSION_OUTPUT_FOLDER = "build";module.exports = {webpack: (config) => {config.plugins[0] = new HtmlWebpackPlugin({...config.plugins[0].userOptions,cache: false,chunks: ["main"],filename: "index.html",template: path.join(__dirname, "src", "Popup", "index.html"),});return {...config,entry: {main: [path.join(__dirname, "src", "Popup", "index.tsx")],...pagesNames.reduce((acc, name) => ({...acc,[name.toLowerCase()]: path.join(__dirname,"src",name,"index.tsx"),}),{}),},optimization: {...config.optimization,runtimeChunk: false,splitChunks: false,},output: {...config.output,chunkFilename: "[name].js",filename: "[name].bundle.js",path: path.resolve(__dirname, CHROME_EXTENSION_OUTPUT_FOLDER),},plugins: [...config.plugins,new webpack.ProgressPlugin(),new CopyWebpackPlugin({patterns: [{force: true,from: path.join(__dirname, "src", "manifest.json"),to: path.join(__dirname, CHROME_EXTENSION_OUTPUT_FOLDER),transform(content) {return Buffer.from(JSON.stringify({version: process.env.npm_package_version,...JSON.parse(content.toString()),}));},},],}),...pagesNames.filter((name) => !["Content", "Background"].includes(name)).map((name) =>new HtmlWebpackPlugin({cache: false,chunks: [name.toLowerCase()],filename: `${name.toLowerCase()}.html`,template: path.join(__dirname, "src", name, "index.html"),})),],};},};
As a result, we should obtain a structure that satisfies Chrome's structural requirements.
Voila! Let's build and load our extension now.
Loading the Chrome Extension
The final step is to load the build into the Chrome extension:
- Navigate to
chrome://extensions/
- Enable Developer mode
- Upload Chrome Extension from the build folder
Conclusions
As demonstrated, while React Create App might not be the most convenient environment to develop Chrome Extensions using React, it is certainly possible, but with a bit of complexity. Here's hoping you find this guide useful.
Do you like the article or have some remarks? Let's discuss it!
Join the Newsletter
Subscribe to be up to date by email.
Cool content and no spam.