You can use this boilerplate code to start developing a Chrome extension using TypeScript/JS, React for the frontend, and Webpack as the build system.
At Duo Labs, we found ourselves creating Chrome extensions with this stack frequently enough that we thought it would be nice to have a consistent starting point. Getting all the individual pieces configured from scratch can be a pain.
Clone this repository, and then, in this directory:
npm install
npx webpack
Your unpacked Chrome extension will be compiled into dist/
. You can load it into Chrome by enabling developer mode on the "Extensions" page, hitting "Load unpacked", and selecting the dist/
folder. You can pack the extension into a .crx
by using the "Pack extension" button on the same page.
Use npx webpack
to recompile after editing.
The default source layout looks like this:
src
├── app
│ ├── background.ts
│ └── content.ts
├── styles
│ └── popup.css
└── ui
└── popup.tsx
background.ts
will get loaded as the extension background script, and will run persistently in the backgroundcontent.ts
will be injected into the URLs matched by dist/manifest.json
's matches
entry (see Match Patterns documentation)popup.tsx
will become the extension's "browser action" popup
popup.tsx
compiles into dist/js/popup.js
. It is loaded into dist/popup.html
by an explicit <script>
tag on that page. dist/popup.html
is static and is not automatically generated by the build process.popup.css
contains styles for the popup. These styles are loaded with style-loader
via the import
line at the top of popup.tsx
(and directly injected into the popup via JavaScript)dist
├── _locales
│ └── en
│ └── messages.json
├── icons
│ ├── icon128.png
│ ├── icon16.png
│ ├── icon19.png
│ └── icon48.png
├── js
│ ├── background.js
│ ├── content.js
│ └── popup.js
├── manifest.json
└── popup.html
dist
contains the Chrome extension. You can delete js/*
, as its contents will be regenerated by webpack
, but the rest of the contents of dist
will not.
We wanted a boilerplate from which we could be productive immediately, without including components we wouldn't immediately need.
This work is inspired by Extensionizr, and the icons in dist/icons
remain under the Extensionizr license.