Chrome: https://chrome.google.com/webstore/detail/fkjghajhfjamfjcmdkbangbeogbagnjf
Firefox: https://addons.mozilla.org/en-US/firefox/addon/twitch-lurker/
This project was sponsored and conceptualized by ErianasVow.
-
git clone ...
-
cd app
andnpm run build:all
-
The source folder for the extension/addon is in
app/build
. -
You can build the background/content scripts separately from the popup.
npm run build:all
builds both.npm run build:popup
builds just the popup (longest wait time).npm run build:scripts
builds just the background/content scripts (shortest wait time).
If you are making changes to background/content scripts, then you need to refresh the extension at
chrome://extensions
.If you are making changes to the popup window, you do not need to refresh the chrome extension (just re-open the popup).
We have the script npm run watch:scripts
, which continuously builds the background/content scripts as you make changes, but you still have to refresh the extension to see the changes. We also have the command npm run watch:popup
which updates the popup as you make changes. You will need to close/reopen the popup to see the changes, but no need to refresh the extension.
There are two major components to this:
- Background scripts
- Content scripts
- React components
Depsite all the files you see, the resulting package uploading to Chrome/Firefox is simply manifest.json
, our background/content scripts, and a popup (index.html
) that is rendered when you click the extension/addon icon.
Our React components are bundled to create our popup. Our app/public/background-scripts/main.ts
is bundled to create our background script. Our app/public/content-scripts/main.ts
is bundled to create our content script. All extension/addon files (icons, manifest, background scripts and content scripts) must be placed inside app/public
. They will be copied over to app/build
.
npm run build:prod
does two things (in this order):
-
rollup
is used to bundle all background scripts into one file calledbackground-script-bundle.js
and all content scripts intocontent-script-bundle.js
.This allows us to use the latest ECMAScript and have great organization of our scripts.
manifest.json
lists onlybackground-script-bundle.js
as a background script andcontent-script-bundle.js
as a content script, sorollup
is expected to be run before packaging the extension (it builds those files).app/public/background-scripts/main.ts
is the entry point for bundling our background scripts (similar for content scripts). Somain.ts
will import other files, likeapp-constants.ts
. -
This project uses
create-react-app
to bootstrap the React app (all of theapp
directory).react-scripts build
is run, which bundles everything fromapp/src
andapp/public
toapp/build
.All of the React componentes are bundled together and rendered on the DOM via the entry point
app/src/index.tsx
. The bundled JS and CSS files are injected intoapp/public/index.html
and then the bundledindex.html
is put intoapp/build
.Note that all of of our
app/public
will be copied intoapp/build
, so that includes ourmanifest.json
,background-script-bundle.js
,content-script-bundle.js
, and other extension/addon files. Therefore, ourmanifest.json
uses all of those files which are bundled into theapp/build
directory with it (index.html
andbackground-script-bundle.js
). Ourapp/build
directory can now be zipped and used as a packaged submission to Chrome/Firefox.
There are three tsconfig
files:
-
tsconfig.json
For our React code and linter.
-
tsconfig.background-scripts.json
For just our background scripts (manually specified in our Rollup config).
-
tsconfig.content-scripts.json
For just our content scripts (manually specified in our Rollup config).
baseUrl: './src'
in tsconfig.json
is used so that imports within any of our React components can use a path relative to app/src
. E.g. a React file deeply nested in directories can use import constants from 'app-constants'
since app-constants
is in app/src
, rather than something like import constants from '../../../app-constants
.
Note that background/content scripts cannot take advantage of this. This would be something nice to implement in the future.
This project uses GitHub actions to run checks and automatic deployments. All PRs created will run a "test" workflow, which simply runs npm run test
and npm run build:prod
. If this fails, it means there is either a lint error, a TypeScript error, or the project did not build for some other reason. This workflow is required to pass before any PR can be merged into master.
Once a commit is made to master (e.g. a PR is merged), two "deploy" workflows will run (one for Firefox and one for Chrome). These workflows build the extension, packages it and deploys it. If the manifest version number is not bumped, then Chrome/Firefox won't accept the package and the workflow will fail, which is fine.
To bump the version (and therefore update the extension in the store), make a separate PR with just the version bump. Not every PR needs to bump the version number afterward. Multiple PRs can be merged to master, then have the version number bumped at a later date to deploy all the changes at once. This also lets us revert commits cleanly without including a version rollback (which is not possible).
Version bumps will loosely follow semantic versioning. The version isn't actually that important since we are not a dependency to anything, but it's our convention.
As mentioned, your code will need to build and pass the linter before it can be merged into master. In addition to that, at least one reviewer with write access will need to approve the PR. Once merged, it goes through the automated deployment process, as mentioned above.
If your PR is addressing an issue, please close the issue and reference the PR on the issue.