Git Product home page Git Product logo

aeksco / react-typescript-web-extension-starter Goto Github PK

View Code? Open in Web Editor NEW
893.0 13.0 81.0 2.78 MB

:desktop_computer: Web Extension starter kit built with React, TypeScript, TailwindCSS, Storybook, Jest, EsLint, Prettier, and Webpack. Supports Google Chrome + Mozilla Firefox + Brave Browser + Microsoft Edge + Opera :fire:

License: MIT License

JavaScript 62.64% TypeScript 34.31% CSS 3.05%
react typescript chrome-extension jest storybook extension-popup eslint mozilla-firefox google-chrome webpack

react-typescript-web-extension-starter's Introduction

GitHub stars GitHub watchers GitHub forks GitHub contributors MIT License GitHub issues GitHub last commit GitHub pull requests PR's Welcome

HitCount Tweet Twitter Follow

React TypeScript Web Extension Starter

๐Ÿ–ฅ๏ธ A Web Extension starter kit built with React, TypeScript, Storybook, EsLint, Prettier, Jest, TailwindCSS, & Webpack. Compatible with Google Chrome, Mozilla Firefox, Brave, and Microsoft Edge.

Example Extension Popup

Getting Started

Run the following commands to install dependencies and start developing

yarn install
yarn dev

Scripts

  • yarn dev - run webpack in watch mode
  • yarn storybook - runs the Storybook server
  • yarn build - builds the production-ready unpacked extension
  • yarn test -u - runs Jest + updates test snapshots
  • yarn lint - runs EsLint
  • yarn prettify - runs Prettier
Loading the extension in Google Chrome

In Google Chrome, open up chrome://extensions in a new tab. Make sure the Developer Mode checkbox in the upper-right corner is turned on. Click Load unpacked and select the dist directory in this repository - your extension should now be loaded.

Installed Extension in Google Chrome

Loading the extension in Brave

In Brave, open up brave://extensions in a new tab. Make sure the Developer Mode checkbox in the upper-right corner is turned on. Click Load unpacked and select the dist directory in this repository - your extension should now be loaded.

Installed Extension in Brave

Loading the extension in Mozilla Firefox

In Mozilla Firefox, open up the about:debugging page in a new tab. Click the This Firefox link in the sidebar. One the This Firefox page, click the Load Temporary Add-on... button and select the manifest.json from the dist directory in this repository - your extension should now be loaded.

Installed Extension in Mozilla Firefox

Loading the extension in Microsoft Edge

In Microsoft Edge, open up edge://extensions in a new tab. Make sure the Developer Mode checkbox in the lower-left corner is turned on. Click Load unpacked and select the dist directory in this repository - your extension should now be loaded.

Installed Extension in Microsoft Edge

Notes

  • This project is a repository template - click the Use this template button to use this starter codebase for your next project.

  • Includes ESLint configured to work with TypeScript and Prettier.

  • Includes tests with Jest - note that the babel.config.js and associated dependencies are only necessary for Jest to work with TypeScript.

  • Recommended to use Visual Studio Code with the Format on Save setting turned on.

  • Example icons courtesy of Heroicons.

  • Includes Storybook configured to work with React + TypeScript. Note that it maintains its own webpack.config.js and tsconfig.json files. See example story in src/components/hello/__tests__/hello.stories.tsx

  • Includes a custom mock for the webextension-polyfill-ts package in src/__mocks__. This allows you to mock any browser APIs used by your extension so you can develop your components inside Storybook.

Built with

Misc. References

Notable forks

  • capaj - Chakra-ui instead of TailwindCSS, Storybook removed
  • DesignString - Vite Js instead of Webpack

react-typescript-web-extension-starter's People

Contributors

aeksco avatar alexrav avatar benjamin-chavez avatar capaj avatar dependabot[bot] avatar drmikecrowe avatar kuboczoch avatar punithbm avatar schuchard avatar willkirkmanm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-typescript-web-extension-starter's Issues

Replace Bootstrap with TailwindCSS

We should replace Bootstrap with TailwindCSS - it's been growing in popularity lately and offers more flexibility than Bootstrap with a more JavaScript-driven approach to customization.

This will likely require the addition of a postcss.config.js file, in addition to tweaking the webpack configuration for both building the extension and running Storybook. We'll also need to update README.md to remove references to Bootstrap.

Manifest V3 breaks support for Firefox and Manifest V2 is no longer supported in Chrome

My original comment can be found in #46.

While the new manifest.json in #46 was tested in Chrome, the Manifest V3 will not work in Firefox:

... we expect to launch MV3 support for all users by the end of 2022.

This breaks cross-browser compatibility for this starter for at least Firefox. Brave apparently plans to continue Manifest V2 support past sunset.

This is complicated further by the fact that new Manifest V2 extensions are already not supported by Chrome.

I think we need a new approach to handle how manifest.json is generated for the dist, perhaps on a per-browser basis?

Verify Brave browser support

Brave should probably work out of the box since it's Chromium based, but we should make sure that this project supports it as a build target.

Error while starting a storybook from default configuration

Context

I can't make a storybook default configuration work by running yarn storybook command.

Expected Behavior

Storybook should start

Current Behavior

The build is failing at 99% with the crash report listed in section below

Failure logs

Full logs
"C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\yarn\bin\yarn.js" run storybook
yarn run v1.22.17
$ start-storybook -p 6006
info @storybook/react v6.4.9
info
info => Loading presets
info => Using implicit CSS loaders
info => Using default Webpack5 setup
<i> [webpack-dev-middleware] wait until bundle finished
10% building 0/16 entries 11/17 dependencies 0/11 modules
info => Ignoring cached manager due to change in manager config
<i> [webpack-dev-middleware] wait until bundle finished
16% building 2/16 entries 2700/2842 dependencies 331/580 modules
warn - The `purge`/`content` options have changed in Tailwind CSS v3.0.
warn - Update your configuration file to eliminate this warning.
99% done plugins webpack-hot-middlewarewebpack built preview 6379bfa5f50c62e53848 in 16879ms
ModuleNotFoundError: Module not found: Error: Can't resolve '..\__mocks__\webextension-polyfill-ts.ts' in 'X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\src\popup'
Did you mean './..\__mocks__\webextension-polyfill-ts.ts'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\Compilation.js:2011:28
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:795:13
  at eval (eval at create (X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:10:1)
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:275:22
  at eval (eval at create (X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:9:1)
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:431:22
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:124:11
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:667:25
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:852:8
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:972:5
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\neo-async\async.js:6883:13
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\lib\NormalModuleFactory.js:959:8
  at finishResolved (X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:278:11)
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:342:25
  at X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:409:24
  at eval (eval at create (X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
resolve '..\__mocks__\webextension-polyfill-ts.ts' in 'X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\src\popup'
Parsed request is a module
using description file: X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\package.json (relative path: ./src/popup)
  Field 'browser' doesn't contain a valid alias configuration
  resolve as module
    X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\src\popup\node_modules doesn't exist or is not a directory
    X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\src\node_modules doesn't exist or is not a directory
    looking for modules in X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\node_modules
      single file module
        using description file: X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\package.json (relative path: ./__mocks__/webextension-polyfill-ts.ts)
          no extension
            Field 'browser' doesn't contain a valid alias configuration
            X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\__mocks__\webextension-polyfill-ts.ts doesn't exist
          .ts
            Field 'browser' doesn't contain a valid alias configuration
            X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\__mocks__\webextension-polyfill-ts.ts.ts doesn't exist
          .tsx
            Field 'browser' doesn't contain a valid alias configuration
            X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\__mocks__\webextension-polyfill-ts.ts.tsx doesn't exist
          .js
            Field 'browser' doesn't contain a valid alias configuration
            X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\__mocks__\webextension-polyfill-ts.ts.js doesn't exist
      X:\AwesomeProjects\aeksco\react-typescript-web-extension-starter\__mocks__\webextension-polyfill-ts.ts doesn't exist
    X:\AwesomeProjects\aeksco\node_modules doesn't exist or is not a directory
    X:\AwesomeProjects\node_modules doesn't exist or is not a directory
    X:\node_modules doesn't exist or is not a directory

WARN Broken build, fix the error above.
WARN You may need to refresh the browser.

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Process finished with exit code 1



Steps to Reproduce

Please provide detailed steps for reproducing the issue.

  1. Download project on the local machine
  2. Install dependencies with yarn
  3. Run command yarn storybook

Specs

I'm using Windows 10 with node version 14.15.0

send message from background to contentscript/web page?

Hi there, I was wondering:
why this starter doesn't have a content script to be able to read the DOM of the web page

I am trying to create a context menu (which works fine) in backgroundPage.ts:

browser.runtime.onInstalled.addListener(function() {
    chrome.contextMenus.create({
        title: "Mage - Explain Code",
        contexts: ["selection"],
        id: "Mage - Explain Code"
    });
});
browser.contextMenus.onClicked.addListener(function (info, tab) {
    if (info.menuItemId === "Mage - Explain Code") {
        let code = info.selectionText
        console.log(code)
        browser.runtime.sendMessage({type: "mageQuery"}); //send msg to tab
    }
})

tf2BPOG

when the context menu button is pressed it should send a message to the current tab and open a tool tip on the highlighted text in the web page.

Which file should I handle this message in? Can this be done inside the popup folder component.tsx, or do I need to create a content script file somehow?

I have spent all day struggling with how to do this so I would very much appreciate help! thank you!

Cannot read properties of undefined (reading 'runtime')

Prerequisites

Please answer the following questions for yourself before submitting an issue:

  • I am running the latest version
  • I checked the documentation and found no answer
  • I checked to make sure that this issue has not already been filed
  • I'm reporting the issue to the correct repository (for multi-repository projects)

Context

Latest Chrome (Version 103.0.5060.134 (Official Build) (x86_64)), running yarn storybook on a fresh install.

Expected Behavior

I expect the Popup story to render.

Current Behavior

The mock for browser appears to be undefined

Failure Information (for bugs)

See the logs below.

Steps to Reproduce

  1. Download this repo
  2. Run yarn install and yarn storybook
  3. Click on the popup in the storybook

Failure Logs

Cannot read properties of undefined (reading 'runtime')
TypeError: Cannot read properties of undefined (reading 'runtime')
    at http://localhost:6007/main.iframe.bundle.js:748:67
    at invokePassiveEffectCreate (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:101741:20)
    at HTMLUnknownElement.callCallback (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:82204:14)
    at Object.invokeGuardedCallbackDev (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:82253:16)
    at invokeGuardedCallback (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:82315:31)
    at flushPassiveEffectsImpl (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:101828:9)
    at unstable_runWithPriority (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:110968:12)
    at runWithPriority$1 (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:89535:10)
    at flushPassiveEffects (http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:101701:14)
    at http://localhost:6007/vendors-node_modules_storybook_addon-actions_dist_esm_preset_addArgs_js-generated-config-entr-a4c2a0.iframe.bundle.js:101578:11

Update Storybook to 5.3

See Storybook migration docs here.

Need to:

  • Delete .storybook/config.js
  • Update main.js (see below)
  • Add preview.js (see below)

main.js:

const path = require("path");

module.exports = {
    stories: ["../src/**/*.stories.tsx"],
    addons: [
        "@storybook/addon-actions/register",
        "@storybook/addon-viewport/register",
    ],
    webpackFinal: async config => {
        config.module.rules.push({
            test: /\.(ts|tsx)$/,
            use: [
                {
                    loader: require.resolve("ts-loader"),
                },
                // Optional
                {
                    loader: require.resolve("react-docgen-typescript-loader"),
                },
            ],
        });

        config.module.rules.push({
            exclude: /node_modules/,
            test: /\.scss$/,
            use: [
                {
                    loader: "style-loader", // Creates style nodes from JS strings
                },
                {
                    loader: "css-loader", // Translates CSS into CommonJS
                },
                {
                    loader: "sass-loader", // Compiles Sass to CSS
                },
            ],
        });

        config.resolve = {
            ...config.resolve,
            extensions: [".ts", ".tsx", ".js"],
            alias: {
                "@src": path.resolve(__dirname, "../src/"),
            },
        };

        return config;
    },
};

preview.js:

import {
    addParameters,
    addDecorator,
    INITIAL_VIEWPORTS,
} from "@storybook/react";
import { withConsole, setConsoleOptions } from "@storybook/addon-console";
import { withInfo } from "@storybook/addon-info";

// Configure Viewports addon
addParameters({
    viewport: {
        viewports: INITIAL_VIEWPORTS,
        defaultViewport: "someDefault",
    },
});

// You'll start to receive all console messages, warnings, errors in your action logger panel - Everything except HMR logs.
setConsoleOptions({
    panelExclude: [],
});

// Setup StoryInfo addon
addDecorator(withInfo);

// You'll receive console outputs as a console,
// warn and error actions in the panel. You might want to know from
// what stories they come. In this case, add withConsole decorator:
addDecorator((storyFn, context) => withConsole()(storyFn)(context));

Missing .nvmrc file

As a new user of your template, I see that there is no .nvmrc file that should contain your node version to make sure that we are using the same one.

If you can tell me which version you are using I can even make a PR for you to help you with that.

Update package.json scripts to define separate manifest.json files for Chrome and Firefox

Got this reply in an /r/react thread:

Nice. I kept looking and looking where you generate the different manifest.json files. But it looks like you used a combined one.

Be aware that there are slight differences in FF and Chrome supported extensions. So I had to keep separate manifest.json files for each browser.

The problem is that each of the browsers doesn't load the extension if the manifest contains invalid stuff that the other one supports ( e.g. optional permissions, or unsupported permissions )

I am on mobile now so difficult for me to diff. But you can see the subtle differences here :

https://github.com/stefanXO/Tab-Manager-Plus/blob/master/manifest.json

https://github.com/stefanXO/Tab-Manager-Plus/blob/master/manifest-firefox.json

There should be separate yarn build:firefox and yarn build:chrome scripts (instead of just having yarn build) that can copy a different source manfiest.json file to account for small variations between the two different browsers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.